aiohttp测试用例404错误及handler传递、client差异咨询
Let's break this down step by step—first fixing that frustrating 404, then clearing up your two key questions.
First: Fixing the 404 Error
The most common reason for a 404 when using aiohttp.test_utils.TestCase is that you haven't registered your handler routes with the test app in the get_app() method. The self.client uses the app returned by get_app(), so if your routes aren't added there, the test app has no idea where to route your requests.
Here's a corrected example that avoids 404s:
from aiohttp import web from aiohttp.test_utils import TestCase, unittest_run_loop # Your handler async def hello(request): name = request.match_info.get('name', 'Anonymous') return web.Response(text=f'Hello, {name}!') class TestHelloApp(TestCase): def get_app(self): # Create your test app instance app = web.Application() # THIS IS THE KEY STEP: Register your handler with a route app.add_routes([ web.get('/hello/{name}', hello), web.get('/hello', hello) ]) return app @unittest_run_loop async def test_hello_endpoint(self): # Now self.client will route to your handler correctly resp = await self.client.get('/hello/Alice') assert resp.status == 200 text = await resp.text() assert text == 'Hello, Alice!'
Double-check that your get_app() method is adding all necessary routes—if you skip this, the test app has no routes to match, hence the 404.
Question 1: What's the difference between test_client and self.client?
Great question! They do the same core job (send test requests to your app) but differ in how you use them:
self.client: This is a pre-configured test client provided directly by theTestCaseclass. It's automatically bound to the app you return fromget_app(), so you don't have to manually create or manage it. It's the "out-of-the-box" convenience option when using the TestCase framework.test_client: This is a standalone context manager fromaiohttp.test_utilsfor when you're not using theTestCaseclass (e.g., writing plain async test functions). You have to manually pass your app instance to it and handle the context yourself. Example:from aiohttp.test_utils import test_client async def test_hello_standalone(): app = web.Application() app.add_routes([web.get('/hello', hello)]) # Manually create and use the client async with test_client(app) as client: resp = await client.get('/hello') assert resp.status == 200
In short: self.client is TestCase's wrapped, easy-to-use version; test_client is the flexible, manual version for non-TestCase tests.
Question 2: Where do I pass handler parameters (like the hello handler's arguments)?
You don't pass handler parameters to self.client—that's not how aiohttp's routing works! Here's the breakdown:
- Handler parameters (like
request, or path variables likenamein thehelloexample) are automatically passed by the aiohttp framework when a request matches the route you registered. - If your handler needs custom dependencies (like a database connection, config values, etc.), you inject those into the app instance in
get_app(), then access them fromrequest.appinside the handler. Example:async def hello_with_config(request): # Access injected dependency from the app greeting_prefix = request.app['config']['greeting'] name = request.match_info.get('name', 'Anonymous') return web.Response(text=f'{greeting_prefix}, {name}!') class TestHelloWithConfig(TestCase): def get_app(self): app = web.Application() # Inject custom config into the app app['config'] = {'greeting': 'Hey there'} # Register the handler with a route app.add_routes([web.get('/hello/{name}', hello_with_config)]) return app
The self.client only needs to know the URL path to hit—routing to the handler and passing parameters is handled entirely by the aiohttp framework and your app's route setup.
内容的提问来源于stack exchange,提问作者Atihska

