Steps and code to set up Django Rest Framework (DRF) test cases with database mocking.
- Set up Django and DRF
Install Django and DRF:
pip install django djangorestframework
Create a Django project and app:
django-admin startproject projectname
cd projectname
python manage.py startapp appname
- Define Models, Serializers, and Views
models.py (appname/models.py):
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
serializers.py (appname/serializers.py):
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = '__all__'
views.py (appname/views.py):
from rest_framework import viewsets
from .models import Item
from .serializers import ItemSerializer
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
urls.py (appname/urls.py):
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ItemViewSet
router = DefaultRouter()
router.register(r'items', ItemViewSet)
urlpatterns = [
path('', include(router.urls)),
]
projectname/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('appname.urls')),
]
- Migrate Database and Create Superuser
python manage.py makemigrations appname
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
- Write Test Cases
tests.py (appname/tests.py):
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from .models import Item
from .serializers import ItemSerializer
class ItemTests(APITestCase):
def setUp(self):
self.item1 = Item.objects.create(name='Item 1', description='Description 1')
self.item2 = Item.objects.create(name='Item 2', description='Description 2')
def test_get_items(self):
url = reverse('item-list')
response = self.client.get(url, format='json')
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, serializer.data)
def test_create_item(self):
url = reverse('item-list')
data = {'name': 'Item 3', 'description': 'Description 3'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Item.objects.count(), 3)
self.assertEqual(Item.objects.get(id=3).name, 'Item 3')
def test_update_item(self):
url = reverse('item-detail', kwargs={'pk': self.item1.id})
data = {'name': 'Updated Item 1', 'description': 'Updated Description 1'}
response = self.client.put(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.item1.refresh_from_db()
self.assertEqual(self.item1.name, 'Updated Item 1')
def test_delete_item(self):
url = reverse('item-detail', kwargs={'pk': self.item2.id})
response = self.client.delete(url, format='json')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Item.objects.count(), 1)
- Run Tests
python manage.py test
This setup provides a basic Django project with DRF and test cases for CRUD operations using the database. The test cases mock the database operations, ensuring isolation and consistency during testing.
Now diving into some more feature tests with Mock, patch etc.
Here are steps and code to write Django Rest Framework (DRF) test cases using mocking and faking features for scenarios like credit card processing.
- Set up Django and DRF
Install Django and DRF:
pip install django djangorestframework
Create a Django project and app:
django-admin startproject projectname
cd projectname
python manage.py startapp appname
- Define Models, Serializers, and Views
models.py (appname/models.py):
from django.db import models
class Payment(models.Model):
card_number = models.CharField(max_length=16)
card_holder = models.CharField(max_length=100)
expiration_date = models.CharField(max_length=5)
amount = models.DecimalField(max_digits=10, decimal_places=2)
status = models.CharField(max_length=10)
serializers.py (appname/serializers.py):
from rest_framework import serializers
from .models import Payment
class PaymentSerializer(serializers.ModelSerializer):
class Meta:
model = Payment
fields = '__all__'
views.py (appname/views.py):
from rest_framework import viewsets
from .models import Payment
from .serializers import PaymentSerializer
class PaymentViewSet(viewsets.ModelViewSet):
queryset = Payment.objects.all()
serializer_class = PaymentSerializer
urls.py (appname/urls.py):
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PaymentViewSet
router = DefaultRouter()
router.register(r'payments', PaymentViewSet)
urlpatterns = [
path('', include(router.urls)),
]
projectname/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('appname.urls')),
]
- Migrate Database and Create Superuser
python manage.py makemigrations appname
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
- Write Test Cases with Mocking and Faking
tests.py (appname/tests.py):
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from unittest.mock import patch
from .models import Payment
from .serializers import PaymentSerializer
class PaymentTests(APITestCase):
def setUp(self):
self.payment_data = {
'card_number': '4111111111111111',
'card_holder': 'John Doe',
'expiration_date': '12/25',
'amount': '100.00',
'status': 'Pending'
}
self.payment = Payment.objects.create(**self.payment_data)
@patch('appname.views.PaymentViewSet.create')
def test_create_payment_with_mock(self, mock_create):
mock_create.return_value = self.payment
url = reverse('payment-list')
response = self.client.post(url, self.payment_data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['card_number'], self.payment_data['card_number'])
@patch('appname.views.PaymentViewSet.perform_create')
def test_create_payment_fake_response(self, mock_perform_create):
def fake_perform_create(serializer):
serializer.save(status='Success')
mock_perform_create.side_effect = fake_perform_create
url = reverse('payment-list')
response = self.client.post(url, self.payment_data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['status'], 'Success')
def test_get_payments(self):
url = reverse('payment-list')
response = self.client.get(url, format='json')
payments = Payment.objects.all()
serializer = PaymentSerializer(payments, many=True)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, serializer.data)
@patch('appname.views.PaymentViewSet.retrieve')
def test_get_payment_with_mock(self, mock_retrieve):
mock_retrieve.return_value = self.payment
url = reverse('payment-detail', kwargs={'pk': self.payment.id})
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['card_number'], self.payment_data['card_number'])
@patch('appname.views.PaymentViewSet.update')
def test_update_payment_with_mock(self, mock_update):
mock_update.return_value = self.payment
updated_data = self.payment_data.copy()
updated_data['status'] = 'Completed'
url = reverse('payment-detail', kwargs={'pk': self.payment.id})
response = self.client.put(url, updated_data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['status'], 'Completed')
@patch('appname.views.PaymentViewSet.destroy')
def test_delete_payment_with_mock(self, mock_destroy):
mock_destroy.return_value = None
url = reverse('payment-detail', kwargs={'pk': self.payment.id})
response = self.client.delete(url, format='json')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Payment.objects.count(), 0)
- Run Tests
python manage.py test
This setup uses unittest.mock.patch
to mock the behavior of various viewset methods in DRF, allowing you to simulate different responses without hitting the actual database or external services.
Top comments (0)