Django DRF API endpoint can be called via Postman but gives back 404 not found in pytest
I'm currently rewriting our Django unit tests (written with django.unittest
library) in pytest, and I'm encountering an issue.
I use a separate conftest.py
file where I store my pytest fixtures and also load my JSON fixtures to fill the database with test data. One of my pytest fixture methods creates a user, and another one creates an authorized client. The user fixture also takes db
as an argument. That's basically the base setup.
The test method calls an endpoint that includes the user_id
in the URL. The call looks something like:
response = authorized_client.get(path=f"/user/{user_id}", headers=header)
Testing the endpoint manually in Postman gives back the user data and a 200
status code. However, pytest returns a 404
status code.
User.objects.exists(id=user_id)
This confirmed that the user exists in the database.
I investigated further and called the endpoint that retrieves all users. The user_id
I used in the call to the endpoint was not included in the response. I suppose that's why I get a 404 back.
The Question
Why do I get User.objects.exists(id=user_id)
but the user with that ID is not actually there when I call the endpoint? Does pytest handle test database isolation differently than django.unittest
so that the viewset can't access the test database? Could that be what is happening here?
I'm still new to pytest, so I wouldn't rule out the possibility that I'm doing something fundamentally wrong, but I couldn't find anything about this. Additional Information
I also tried calling the viewset directly with something similar to this:
@pytest.mark.django_db(transaction=True)
def test_viewset_direct_call(test_user):
factory = APIRequestFactory()
request = factory.get(f"/user/{test_user.id}")
view = UserViewSet.as_view({"get": "retrieve"})
response = view(request, pk=test_user.id)
assert response.status_code == 200
This also results in 404 not found.
My pytest.fixture
for creating the test user looks something like this:
@pytest.fixture
def test_user(db) -> User:
with transaction.atomic():
return User.objects.create_user(<test credentials go here>)