Setting a property into request in Django test client

330 views Asked by At

I have a middleware (tenant_schemas.BaseTenantMiddleware) that will inject tenant property into the request object. I can't use that middleware when unit testing.

In a view I can then get the tenant object from the request. This view is mapped to the URL "myapp:member_info".

class MemberView(TemplateView):
    template_name = 'myapp/member.html'
    
    def get_context_data(self, member_id=None, *args, **kwargs):
        ctx = super().get_context_data(*args, **kwargs)
        tenant = self.request.tenant
        ctx['tenant_name'] = tenant.name
        return ctx

This view works when the project is run normally as the middleware will set request.tenant correctly.

Now, if I want to test this view I try to write following test:

class MemberViewTest(TestCase):
    def setUp(self):
        self.tenant = Tenant(name="test tenant")
        self.member = Member.objects.create(
            first_name='Test',
            last_name='Person')
        
    def test_saldo(self):
        self.client = Client(tenant=self.tenant) # Here I try to inject the tenant into the request
        print(self.client.defaults) # This will print {'tenant': <Tenant: test tenant>}
        response = self.client.get(reverse('myapp:member_info', kwargs={ 'tenant': self.tenant, 'member_id': self.member.token }))

This test fails to error:

File "myapp/views.py", line xxx, in get_context_data
    tenant = self.request.tenant
AttributeError: 'WSGIRequest' object has no attribute 'tenant'

So, the django.tests.Client class is not injecting the defaults to the request.

One thing I tried is to override the RequestFactory (https://github.com/django/django/blob/ac6c4260074de43a978e5c6553ef89441e1d6748/django/test/client.py#L308) so that it would inject the tenant.

class TenantRequestFactory(RequestFactory):
    def request(self, **request):
        req = super().request(**request)
        req.tenant = Tenant()
        print(req)
        return req
        
class TenantClient(Client, TenantRequestFactory):
    pass

views.py
    def test_saldo(self):
        self.client = TenantClient(tenant=self.tenant)

But the TenantRequestFactory.request() is never called (the print command is not hitting). I don't know if I should subclass it some other way? In client.py the Client class is created like this: class Client(ClientMixin, RequestFactory)

0

There are 0 answers