|
1 | 1 | import asyncio
|
| 2 | +from unittest import mock |
2 | 3 |
|
3 | 4 | import pytest
|
4 | 5 |
|
@@ -126,6 +127,44 @@ async def test():
|
126 | 127 | loop.close()
|
127 | 128 |
|
128 | 129 |
|
| 130 | +@pytest.mark.parametrize("mode", ("auto", "on")) |
| 131 | +def test_lifespan_on_when_app_is_cancelled(mode): |
| 132 | + def get_app(started_event: asyncio.Event): |
| 133 | + async def app(scope, receive, send): |
| 134 | + started_event.set() |
| 135 | + await receive() |
| 136 | + pytest.fail("Should be cancelled before it gets here.") |
| 137 | + |
| 138 | + return app |
| 139 | + |
| 140 | + async def test(): |
| 141 | + # Python 3.8/3.9 doesn't allow us to instantiate an asyncio.Event object |
| 142 | + # while outside of a running event loop context |
| 143 | + started_event = asyncio.Event() |
| 144 | + |
| 145 | + config = Config(app=get_app(started_event), lifespan=mode) |
| 146 | + lifespan = LifespanOn(config) |
| 147 | + |
| 148 | + main_lifespan_task = asyncio.create_task(lifespan.main()) |
| 149 | + |
| 150 | + started_response = await started_event.wait() |
| 151 | + assert started_response |
| 152 | + assert not lifespan.shutdown_event.is_set() |
| 153 | + |
| 154 | + with mock.patch.object(lifespan, "logger") as logger: |
| 155 | + main_lifespan_task.cancel() |
| 156 | + await main_lifespan_task |
| 157 | + |
| 158 | + assert not lifespan.error_occured |
| 159 | + logger.info.assert_called_with("Lifespan task cancelled.") |
| 160 | + assert lifespan.startup_event.is_set() |
| 161 | + assert lifespan.shutdown_event.is_set() |
| 162 | + |
| 163 | + loop = asyncio.new_event_loop() |
| 164 | + loop.run_until_complete(test()) |
| 165 | + loop.close() |
| 166 | + |
| 167 | + |
129 | 168 | @pytest.mark.parametrize("mode", ("auto", "on"))
|
130 | 169 | @pytest.mark.parametrize("raise_exception", (True, False))
|
131 | 170 | def test_lifespan_with_failed_startup(mode, raise_exception, caplog):
|
|
0 commit comments