question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AssertionError with middleware and TemplateResponse

See original GitHub issue
diff --git i/tests/test_templates.py w/tests/test_templates.py
index b48373e..57dee91 100644
--- i/tests/test_templates.py
+++ w/tests/test_templates.py
@@ -20,6 +20,11 @@ def test_templates(tmpdir):
     async def homepage(request):
         return templates.TemplateResponse("index.html", {"request": request})

+    @app.middleware("http")
+    async def noop(request, call_next):
+        response = await call_next(request)
+        return response
+
     client = TestClient(app)
     response = client.get("/")
     assert response.text == "<html>Hello, <a href='http://testserver/'>world</a></html>"

causes:

tests/test_templates.py:29: in test_templates
    response = client.get("/")
.venv/lib/python3.7/site-packages/requests/sessions.py:546: in get
    return self.request('GET', url, **kwargs)
starlette/testclient.py:421: in request
    json=json,
.venv/lib/python3.7/site-packages/requests/sessions.py:533: in request
    resp = self.send(prep, **send_kwargs)
.venv/lib/python3.7/site-packages/requests/sessions.py:646: in send
    r = adapter.send(request, **kwargs)
starlette/testclient.py:238: in send
    raise exc from None
starlette/testclient.py:235: in send
    loop.run_until_complete(self.app(scope, receive, send))
/usr/lib/python3.7/asyncio/base_events.py:584: in run_until_complete
    return future.result()
starlette/applications.py:134: in __call__
    await self.error_middleware(scope, receive, send)
starlette/middleware/errors.py:122: in __call__
    raise exc from None
starlette/middleware/errors.py:100: in __call__
    await self.app(scope, receive, _send)
starlette/middleware/base.py:25: in __call__
    response = await self.dispatch_func(request, self.call_next)
tests/test_templates.py:21: in noop
    response = await call_next(request)
starlette/middleware/base.py:47: in call_next
    assert message["type"] == "http.response.start"
E   AssertionError

message is {'type': 'http.response.template', 'template': <Template 'index.html'>, 'context': {'request': <starlette.requests.Request object at 0x7ff4a2d21e48>}} there.

This appears to be an issue with the test client only though. Do I understand it correctly that the “http.response.template” extension is only used with tests?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:15
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

4reactions
fgimiancommented, Oct 6, 2020

A slightly neater solution, which can be injected into any test which already has the client injected:

@pytest.fixture
def exclude_middleware():
    user_middleware = app.user_middleware.copy()
    app.user_middleware = []
    app.middleware_stack = app.build_middleware_stack()
    yield
    app.user_middleware = user_middleware
    app.middleware_stack = app.build_middleware_stack()

Keeping my fingers crossed that this problem gets fixed soon 😄

Huge thanks Fotis

4reactions
samuelcolvincommented, Apr 11, 2020

I currently have a hacky workaround for this.

Subclass Jinja2Templates and modify it to not send the context, this means you can’t test against the template context, but at least doesn’t fail. Does anyone have a better workaround than this (e.g. doesn’t involve changing anything in the application code, still allows tests with context)?

from starlette.responses import Response
from starlette.templating import Jinja2Templates as _Jinja2Templates, _TemplateResponse


class TestableJinja2Templates(_Jinja2Templates):
    def TemplateResponse(
        self,
        name: str,
        context: dict,
        status_code: int = 200,
        headers: dict = None,
        media_type: str = None,
        background=None,
    ) -> _TemplateResponse:
        if "request" not in context:
            raise ValueError('context must include a "request" key')
        template = self.get_template(name)
        return CustomTemplateResponse(
            template,
            context,
            status_code=status_code,
            headers=headers,
            media_type=media_type,
            background=background,
        )


class CustomTemplateResponse(_TemplateResponse):
    async def __call__(self, scope, receive, send) -> None:
        # context sending removed
        await Response.__call__(self, scope, receive, send)
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to return an rest_framework.response object from a ...
When the content of the response is explicitly set by assigning response.content. After passing through template response middleware, but before ...
Read more >
[Django] #33588: never_cache and cache_page applied out ...
Severity: Normal | cache,never_cache,cache_page,TemplateResponse, ... decorator is based on `CacheMiddleware` by using
Read more >
Templates - FastAPI
Use the templates you created to render and return a TemplateResponse , passing the request as one of the key-value pairs in the...
Read more >
Assertion error at: Django-rest-Framework
AuthenticationMiddleware ', 'django.contrib.messages.middleware. ... File "/Library/Python/2.7/site-packages/django/template/response.py" in render 103.
Read more >
TemplateResponse and SimpleTemplateResponse | Django
Unlike basic HttpResponse objects, TemplateResponse objects retain the details of ... After passing through template response middleware, but before passing ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found