How to write concise CRUD tests in Django REST Framework
To write tests for Django REST framework's ListCreateAPIView
and RetrieveUpdateDestroyAPIView
, you will need to do the following:
- Set up your test environment and create a test case subclassing
APITestCase
from Django REST framework's test utilities. - Define a test method in your test case for each view you want to test.
- Within each test method, use the
client
attribute of the test case to send requests to the view and make assertions about the response.
Here is an example of how you could write tests for a simple API that has a ListCreateAPIView
for a Person
model and a RetrieveUpdateDestroyAPIView
for individual Person
instances:
# myapp/models.py
class Person(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveIntegerField(default=0)
slug = models.CharField(max_length=50)
# myapp/rest/serializers.py
from rest_framework import serializers
from ..model import Person
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('name', 'age', 'slug')
# myapp/rest/tests/test_people_endpoints.py
from rest_framework.test import APITestCase
from ...models import Person
from ..serializers import PersonSerializer
class PersonAPITestCase(APITestCase):
def setUp(self):
self.alice = {'name': 'Alice', 'slug': 'alice', 'age': 18}
self.bob = {'name': 'Bob', 'slug': 'bob', 'age': 20}
self.charlie = {'name': 'Charlie', slug: 'Charlie', 'age': 25}
def test_post_peoplelist(self):
# send a POST request to the ListCreateAPIView with the data for a new person
response = self.client.post('/api/people', data=self.alice)
# assert that the response status code is correct
self.assertEqual(response.status_code, 201)
# assert that the returned data is correct
self.assertEqual(response.data, PersonSerializer(self.alice).data)
def test_get_peoplelist(self):
# send a GET request to the ListCreateAPIView
response = self.client.get('/api/people')
# assert that the response status code is correct
self.assertEqual(response.status_code, 200)
# assert that the returned data is correct
self.assertEqual(response.data, PersonSerializer([self.bob, self.alice], many=True).data)
def test_retrieve_person(self):
# send a GET request to the RetrieveUpdateDestroyAPIView for an individual person
response = self.client.get(f'/api/people/{self.bob.slug}')
# assert that the response status code is correct
self.assertEqual(response.status_code, 200)
# assert that the returned data is correct
self.assertEqual(response.data, PersonSerializer(self.bob).data)
def test_update_person(self):
payload = {'name': 'Robert', 'age': 31}
# send a PUT request to the RetrieveUpdateDestroyAPIView with updated data for an individual person
response = self.client.patch(f'/api/people/{self.bob.slug}', data=payload)
# assert that the response status code is correct
self.assertEqual(response.status_code, 200)
# assert that the returned data is correct
self.assertEqual(response.data, PersonSerializer(self.bob.update(payload)).data
def test_destroy_person(self):
# send a DELETE request to the RetrieveUpdateDestroyAPIView for an individual person
response = self.client.delete('/api/people/{self.bob.slug}')
# assert that the response status code is correct
self.assertEqual(response.status_code, 204)
# assert that the person was not in the list of people
response = self.client.get('/api/people')
self.assertNotIn(self.bob_data, response.data)