3

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

6
  • Why not use django-rest-framework? Did you try and find any problem with that? Commented Dec 19, 2019 at 10:46
  • I'm not sure I understand your comment, do you mean using DRF for tests? I have all other tests in pytest and it would be nice to stick with it. Plus I would really like to know why it doesn't work. Commented Dec 19, 2019 at 12:21
  • I'm talking about this: django-rest-framework.org/api-guide/testing Commented Dec 19, 2019 at 13:01
  • @luistm That's exactly how I'm running a test - using from rest_framework.test import APIClient, sending the request with client.get() and asserting the response, right? Can you elaborate? Commented Dec 19, 2019 at 13:22
  • You are not storing the create transaction, try changing the deco to @pytest.mark.django_db(transaction=True) Commented Dec 23, 2019 at 11:18

2 Answers 2

1

This is a very simple example. But maybe you can make it work like this:

from rest_framework.test import APITransactionTestCase
from rest_framework.test import status

class TestThis(APITransactionTestCase):
    def test_this(self):
        data = {"key": "value"}
        response = self.client.post("/api/resource", data=data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

I hope it helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Not really. I know how to do that with TestCase and factories, but I'd rather avoid writing factories when I have fixtures ready from other tests. There must be a way to make them work. But thanks for trying.
1

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.

1 Comment

When it comes to the trailing slack, maybe this can help: stackoverflow.com/questions/46163838/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.