Search code examples
pythondjangodjango-rest-frameworkpytestpytest-django

How to properly test Django API ListView with PyTest?


I have an API ListView endpoint, which works properly when I shoot it with Postman, but returns empty queryset and status 404 in tests:

test result:

web_1  | >       assert response.status_code == 200
web_1  | E       assert 404 == 200

I use pytest fixture to create my object:

conftest.py


@pytest.fixture
def event(system, new_conflict):
    return Event.objects.create(
        system=system,
        event_type='new_conflict',
        details=new_conflict
    )

Fixtures work fine in other (not API) tests, so I believe the problem might be in the way I'm testing my API. In pycharm debugger I can see that the view is executed, so it's not a url problem.

In postman, this endpoint properly returns a json with Event objects and status 200.

test_api.py


from rest_framework.test import APIClient

from event_finder.models import Event
import pytest


@pytest.mark.django_db
def test_list_events_all(event):
    client = APIClient()
    response = client.get(path='/api/events/', format='json')

    assert response.status_code == 200

views.py

from rest_framework.generics import ListAPIView

from event_finder.models import Event
from event_finder.serializers import EventSerializer


class ListView(ListAPIView):
    queryset = Event.objects.all()
    serializer_class = EventSerializer


Solution

  • Okay, apparently I'm an idiot and problem was totally different. My URL didn't work because of / in the end. Changed it to:

    response = client.get(path='/api/events',
                              format='json')
    

    and it works just fine. No idea why I didn't catch that before, I was running through the whole app with Pycharm debugger and the view was executed.

    To be honest after reading the docs I'm quite surprised my fixture works. According to the docs I should add db fixture to my fixture, but it works just fine without it.

    Thanks for help and sorry for wasting your time.