|
1 | 1 | import typing |
| 2 | +from collections.abc import Callable |
2 | 3 |
|
3 | 4 | import faststream |
| 5 | +import pytest |
4 | 6 | from faststream import TestApp |
| 7 | +from faststream.asgi import AsgiFastStream |
5 | 8 | from faststream.nats import NatsBroker, TestNatsBroker |
6 | 9 | from modern_di import Container |
7 | 10 |
|
@@ -95,3 +98,51 @@ async def test_manage_lifespan_false_lets_the_user_own_the_root() -> None: |
95 | 98 |
|
96 | 99 | assert container.closed |
97 | 100 | assert app_instance.finalized == 1 |
| 101 | + |
| 102 | + |
| 103 | +class _CloseCountingContainer(Container): |
| 104 | + close_calls = 0 |
| 105 | + |
| 106 | + async def close_async(self) -> None: |
| 107 | + self.close_calls += 1 |
| 108 | + await super().close_async() |
| 109 | + |
| 110 | + |
| 111 | +def _setup_on_faststream(broker: NatsBroker, container: Container) -> faststream.FastStream | AsgiFastStream: |
| 112 | + app = faststream.FastStream(broker) |
| 113 | + setup_di(app, container) |
| 114 | + return app |
| 115 | + |
| 116 | + |
| 117 | +def _setup_on_asgi(broker: NatsBroker, container: Container) -> faststream.FastStream | AsgiFastStream: |
| 118 | + app = AsgiFastStream(broker) |
| 119 | + setup_di(app, container) |
| 120 | + return app |
| 121 | + |
| 122 | + |
| 123 | +def _setup_then_as_asgi(broker: NatsBroker, container: Container) -> faststream.FastStream | AsgiFastStream: |
| 124 | + app = faststream.FastStream(broker) |
| 125 | + setup_di(app, container) |
| 126 | + return app.as_asgi() |
| 127 | + |
| 128 | + |
| 129 | +@pytest.mark.parametrize("build_app", [_setup_on_faststream, _setup_on_asgi, _setup_then_as_asgi]) |
| 130 | +async def test_after_shutdown_hook_registered_after_setup_di_sees_the_open_root( |
| 131 | + build_app: Callable[[NatsBroker, Container], faststream.FastStream | AsgiFastStream], |
| 132 | +) -> None: |
| 133 | + broker = NatsBroker() |
| 134 | + container = _CloseCountingContainer(groups=[Dependencies]) |
| 135 | + app = build_app(broker, container) |
| 136 | + seen: list[tuple[Finalizable, int]] = [] |
| 137 | + |
| 138 | + @app.after_shutdown |
| 139 | + def user_hook() -> None: |
| 140 | + instance = container.resolve_provider(Dependencies.app_finalizable) |
| 141 | + seen.append((instance, instance.finalized)) |
| 142 | + |
| 143 | + for cycle in (1, 2): |
| 144 | + async with TestNatsBroker(broker), TestApp(app): |
| 145 | + pass |
| 146 | + assert [(instance.finalized, at_hook) for instance, at_hook in seen] == [(1, 0)] * cycle |
| 147 | + assert container.closed |
| 148 | + assert container.close_calls == cycle |
0 commit comments