pytest-django won't allow database access even with mark
Asked Answered
A

2

11

I'm having a difficult time figuring out what is wrong with my setup. I'm trying to test a login view, and no matter what I try, I keep getting:

Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

My test:

import pytest

from ..models import User


@pytest.mark.django_db
def test_login(client):
    # If an anonymous user accesses the login page:
    response = client.get('/users/login/')
    # Then the server should respond with a successful status code:
    assert response.status_code == 200

    # Given an existing user:
    user = User.objects.get(username='user')
    # If we attempt to log into the login page:
    response = client.post('/users/login/', {'username': user.username, 'password': 'somepass'})
    # Then the server should redirect the user to the default redirect location:
    assert response.status_code == 302

My conftest.py file, in the same tests directory:

import pytest

from django.core.management import call_command


@pytest.fixture(autouse=True)
def django_db_setup(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        call_command('loaddata', 'test_users.json')

My pytest.ini file (which specifies the correct Django settings file):

[pytest]
DJANGO_SETTINGS_MODULE = config.settings

I'm stumped. I've tried using scope="session" like in the documentation together with either an @pytest.mark.django_db mark, a db fixture (as a parameter to the test function), or both with no luck. I've commented out each line of the test to figure out which one was triggering the problem, but couldn't figure it out. I could only get the test to run at all if I removed all db-dependent fixtures/marks/code from the test and had a simple assert True. I don't believe the issue is in my Django settings, as the development server runs fine and is able to access the database.

What am I missing here?

Alisaalisan answered 31/5, 2019 at 5:37 Comment(1)
Can you provide a minimal reproducible example?Leftward
A
11

Apparently this is a case of "deceiving exception syndrome". I had a migration that created groups with permissions, and since tests run all migrations at once, the post-migrate signal that creates the permissions that migration depends on was never run before getting to that migration.

It seems that if there is any database-related error before the actual tests start running, this exception is raised, which makes it very difficult to debug exactly what is going wrong. I ended up updating my migration script to manually cause permissions to be created so that the migration could run, and the error went away.

Alisaalisan answered 4/6, 2019 at 16:10 Comment(1)
This answer provides an alternative solution. It suggests calling the post-migrate signal manually, forcing the permissions creation at the test setup. This way I can avoid creating permissions that are already defined by Django, or created through the permissions attribute from the model's Meta.Ecphonesis
A
7

You can add below code in your conftest.py as per the official documentation to allow DB access without django_db marker.

@pytest.fixture(autouse=True)
def enable_db_access_for_all_tests(db):
    pass

Ref: https://pytest-django.readthedocs.io/en/latest/faq.html#how-can-i-give-database-access-to-all-my-tests-without-the-django-db-marker

Anacreon answered 9/12, 2020 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.