Skip to content

Commit 2db48c9

Browse files
🐛 Fix: 修复测试全局 asgi driver lifespan 问题 (#30)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 5ab84d7 commit 2db48c9

3 files changed

Lines changed: 84 additions & 29 deletions

File tree

nonebug/fixture.py

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,80 @@
1+
from contextlib import nullcontext, asynccontextmanager
2+
13
import pytest
4+
from async_asgi_testclient import TestClient
25

36
from nonebug.app import App
7+
from nonebug.mixin.driver import set_global_client
48

59
from . import NONEBOT_INIT_KWARGS, NONEBOT_START_LIFESPAN
610

711

12+
@asynccontextmanager
13+
async def lifespan_ctx():
14+
import nonebot
15+
from nonebot import logger
16+
from nonebot.drivers import ASGIMixin
17+
18+
driver = nonebot.get_driver()
19+
20+
if isinstance(driver, ASGIMixin):
21+
# if the driver has an asgi application
22+
# use asgi lifespan to startup/shutdown
23+
ctx = TestClient(driver.asgi)
24+
set_global_client(ctx)
25+
else:
26+
ctx = driver._lifespan
27+
28+
try:
29+
await ctx.__aenter__()
30+
except Exception as e:
31+
logger.opt(colors=True, exception=e).error(
32+
"<r><bg #f8bbd0>Error occurred while running startup hook."
33+
"</bg #f8bbd0></r>"
34+
)
35+
raise
36+
37+
try:
38+
yield
39+
finally:
40+
try:
41+
await ctx.__aexit__(None, None, None)
42+
except Exception as e:
43+
logger.opt(colors=True, exception=e).error(
44+
"<r><bg #f8bbd0>Error occurred while running shutdown hook."
45+
"</bg #f8bbd0></r>"
46+
)
47+
48+
849
@pytest.fixture(scope="session", autouse=True)
9-
async def nonebug_init(request: pytest.FixtureRequest): # noqa: PT004
50+
def _nonebot_init(request: pytest.FixtureRequest):
1051
"""
1152
Initialize nonebot before test case running.
1253
"""
1354
import nonebot
14-
from nonebot import logger
1555
from nonebot.matcher import matchers
1656

1757
from nonebug.provider import NoneBugProvider
1858

1959
nonebot.init(**request.config.stash.get(NONEBOT_INIT_KWARGS, {}))
2060
matchers.set_provider(NoneBugProvider)
2161

62+
63+
@pytest.fixture(scope="session", autouse=True)
64+
async def after_nonebot_init(_nonebot_init: None): # noqa: PT004
65+
pass
66+
67+
68+
@pytest.fixture(scope="session", autouse=True)
69+
async def nonebug_init( # noqa: PT004
70+
_nonebot_init: None, after_nonebot_init: None, request: pytest.FixtureRequest
71+
):
2272
run_lifespan = request.config.stash.get(NONEBOT_START_LIFESPAN, True)
23-
driver = nonebot.get_driver()
24-
if run_lifespan:
25-
try:
26-
await driver._lifespan.startup()
27-
except Exception as e:
28-
logger.opt(colors=True, exception=e).error(
29-
"<r><bg #f8bbd0>Error occurred while running startup hook."
30-
"</bg #f8bbd0></r>"
31-
)
32-
raise
3373

34-
try:
74+
ctx = lifespan_ctx() if run_lifespan else nullcontext()
75+
76+
async with ctx:
3577
yield
36-
finally:
37-
if run_lifespan:
38-
try:
39-
await driver._lifespan.shutdown()
40-
except Exception as e:
41-
logger.opt(colors=True, exception=e).error(
42-
"<r><bg #f8bbd0>Error occurred while running shutdown hook."
43-
"</bg #f8bbd0></r>"
44-
)
4578

4679

4780
@pytest.fixture(name="app")
@@ -53,4 +86,4 @@ def nonebug_app(nonebug_init) -> App:
5386
return App()
5487

5588

56-
__all__ = ["nonebug_init", "nonebug_app"]
89+
__all__ = ["after_nonebot_init", "nonebug_init", "nonebug_app"]

nonebug/mixin/driver.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@
66

77
from nonebug.base import BaseApp, Context
88

9+
_global_client: Optional[TestClient] = None
10+
11+
12+
def set_global_client(client: TestClient):
13+
global _global_client
14+
15+
if _global_client is not None:
16+
raise RuntimeError()
17+
18+
_global_client = client
19+
20+
21+
def get_global_client() -> Optional[TestClient]:
22+
return _global_client
23+
924

1025
@final
1126
class ServerContext(Context):
@@ -14,18 +29,21 @@ def __init__(
1429
app: BaseApp,
1530
*args,
1631
asgi: ASGIApplication,
32+
client: Optional[TestClient] = None,
1733
**kwargs,
1834
):
1935
super().__init__(app, *args, **kwargs)
2036
self.asgi = asgi
37+
self.specified_client = client
2138
self.client = TestClient(self.asgi)
2239

2340
def get_client(self) -> TestClient:
24-
return self.client
41+
return self.specified_client or self.client
2542

2643
async def setup(self) -> None:
2744
await super().setup()
28-
await self.stack.enter_async_context(self.client)
45+
if self.specified_client is None:
46+
await self.stack.enter_async_context(self.client)
2947

3048

3149
# @final
@@ -50,8 +68,12 @@ class DriverMixin(BaseApp):
5068
def test_server(self, asgi: Optional[ASGIApplication] = None) -> ServerContext:
5169
import nonebot
5270

71+
client = None
72+
if asgi is None:
73+
client = get_global_client()
74+
5375
asgi = asgi or nonebot.get_asgi()
54-
return ServerContext(self, asgi=asgi)
76+
return ServerContext(self, asgi=asgi, client=client)
5577

5678
# def test_client(self):
5779
# ...

tests/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
from nonebot.plugin import Plugin
66

77
from nonebug import NONEBOT_INIT_KWARGS
8-
from nonebug.fixture import * # noqa: F403
8+
from nonebug.fixture import nonebug_app, nonebug_init, _nonebot_init # noqa: F401
99

1010

1111
def pytest_configure(config: pytest.Config) -> None:
1212
config.stash[NONEBOT_INIT_KWARGS] = {"custom_key": "custom_value"}
1313

1414

15-
@pytest.fixture(scope="session")
16-
def load_plugin(nonebug_init: None) -> set[Plugin]:
15+
@pytest.fixture(scope="session", autouse=True)
16+
async def after_nonebot_init(_nonebot_init: None) -> set[Plugin]: # noqa: F811
1717
return nonebot.load_plugins(str(Path(__file__).parent / "plugins"))

0 commit comments

Comments
 (0)