Introduction
External services (APIs, databases, email) should be mocked in tests for speed, reliability, and isolation.
Key Concepts
Mock: Fake object that replaces a real dependency.
Responses Library: Mock HTTP requests elegantly.
Deep Dive
Mocking HTTP Requests
pythonimport responses import requests class ExternalAPITests(TestCase): @responses.activate def test_fetch_weather_data(self): responses.add( responses.GET, 'https://api.weather.com/current', json={'temp': 72, 'condition': 'sunny'}, status=200 ) result = get_weather('NYC') self.assertEqual(result['temp'], 72) @responses.activate def test_api_error_handling(self): responses.add( responses.GET, 'https://api.weather.com/current', json={'error': 'Service unavailable'}, status=503 ) with self.assertRaises(ServiceUnavailable): get_weather('NYC')
Mocking with unittest.mock
pythonfrom unittest.mock import patch, Mock class PaymentTests(TestCase): @patch('myapp.payments.stripe.Charge.create') def test_successful_payment(self, mock_charge): mock_charge.return_value = Mock(id='ch_123', status='succeeded') result = process_payment(amount=100, token='tok_visa') self.assertTrue(result.success) mock_charge.assert_called_once_with( amount=10000, # cents currency='usd', source='tok_visa' )
Mocking Celery Tasks
pythonfrom unittest.mock import patch class TaskTests(TestCase): @patch('myapp.tasks.send_notification.delay') def test_notification_queued(self, mock_delay): create_order(user=self.user) mock_delay.assert_called_once()
Real World Context
Modern Django applications integrate with payment processors (Stripe, PayPal), email services (SendGrid, SES), cloud storage (S3), and dozens of third-party APIs. Without mocking, your test suite would require active accounts with every service, internet access, and would run orders of magnitude slower. Mocking is not optional for professional Django development.
Common Pitfalls
- Mocking too deep: Mock at the boundary (requests.get, stripe.Charge.create), not internal helper functions.
- Forgetting to test error responses: Mock both success and failure cases -- 200 and 503 responses from external APIs.
- Not verifying request parameters: Use assert_called_with() to ensure your code sends the right data to external services.
Best Practices
- Mock at the boundary: Mock where your code meets external systems.
- Use responses for HTTP: Cleaner than patching requests.
- Verify calls: Use assert_called_with() to verify correct usage.
Summary
Mock external services to make tests fast and reliable. Use the responses library for HTTP mocking. Always verify mocks were called correctly.