Search code examples
djangodjango-testingpython-mock

How to mock django.db.connection.schema_name


I am trying to test a multi-tenant django app. I'm trying to mock a connection to the public tenant:

class ViewsTest(ViewTestUtilsMixin, TenantTestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_some_public_only_view(self)
         # generate a request instance so we can call our view directly
        request = self.factory.get('/')

        with patch('tenant.views.connection.schema_name', return_value=get_public_schema_name()):
            response = some_public_only_view(request)  
            self.assertEqual(response.status_code, 200)

However, when I debug this to check the value of schema_name in the some_public_only_view method during the test, I get this:

<MagicMock name='schema_name' id='140578910478880'>,

so at least I know I'm patching the correct location. The problem is that schema_name is not a method, so it doesn't use the return value.

So how can I mock the schema_name? The view being testing is using it in this way in tenant/views.py

def some_public_only_view(request):

    if connection.schema_name == get_public_schema_name():
         # do stuff
         # returns a good view, 200
    else:
         raise Http404

I also tried this:

with patch.object('tenant.views.connection', 'schema_name', get_public_schema_name()):

which gives me: AttributeError: tenant.views.connection does not have the attribute 'schema_name'


Solution

  • You can mock an object property using PropertyMock in this way:

    @patch('tenant.views.connection.schema_name', new_callable=PropertyMock(return_value="abc"))
    def test_some_public_only_view(self, mock_schema):
    ...
    

    here the documentation https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock

    Anyway, there is nothing wrong with your approach, in fact, I've also tested your code:

    with patch.object('tenant.views.connection', 'schema_name', get_public_schema_name()):
    

    and I didn't get any error.

    I've experienced this error AttributeError: tenant.views.connection does not have the attribute 'schema_name' when I tried first without having set up the right database backend, that should come from the tenant_schemas library, one of these: postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle', I've used tenant_schemas.postgresql_psycopg2

    If this is the reason (database settings misconfiguration), if you try to run your test without patching schema_name, you should have this error

    AttributeError: 'DatabaseWrapper' object has no attribute 'schema_name'
    

    as mentioned here: https://github.com/bernardopires/django-tenant-schemas/issues/328