0
0
DjangoHow-ToBeginner · 3 min read

How to Mock in Django Test: Simple Guide with Examples

To mock in a Django test, use Python's built-in unittest.mock library to replace parts of your code with mock objects. Apply @patch decorators or context managers to mock functions, methods, or classes during test execution.
📐

Syntax

Use unittest.mock.patch to replace a target object with a mock during a test. You can apply it as a decorator or a context manager.

  • @patch('path.to.target'): Decorates a test method to mock the target.
  • with patch('path.to.target') as mock_obj:: Temporarily mocks inside a block.
  • The mocked object is passed as an argument to the test method or available inside the block.
python
from unittest.mock import patch

@patch('myapp.utils.send_email')
def test_email_sending(mock_send_email):
    # mock_send_email replaces send_email during this test
    mock_send_email.return_value = True
    result = some_function_that_calls_send_email()
    assert result is True
    mock_send_email.assert_called_once()
💻

Example

This example shows how to mock an external API call inside a Django test to avoid real network requests and control the response.

python
from django.test import TestCase
from unittest.mock import patch

# Imagine this function calls an external API
from myapp.utils import fetch_data

def fetch_data():
    import requests
    response = requests.get('https://api.example.com/data')
    return response.json()

class FetchDataTest(TestCase):
    @patch('myapp.utils.requests.get')
    def test_fetch_data_mocked(self, mock_get):
        mock_get.return_value.json.return_value = {'key': 'value'}
        data = fetch_data()
        self.assertEqual(data, {'key': 'value'})
        mock_get.assert_called_once_with('https://api.example.com/data')
Output
Ran 1 test in 0.001s OK
⚠️

Common Pitfalls

  • Mocking the wrong import path: Always patch where the object is used, not where it is defined.
  • Not restoring mocks: Use @patch or context managers to auto-restore after tests.
  • Over-mocking: Mock only external dependencies, not the code you want to test.
  • Ignoring mock assertions: Always check if mocks were called as expected.
python
from unittest.mock import patch

# Wrong patch target - patching original module instead of usage location
@patch('myapp.external_api.call_api')  # Incorrect if 'call_api' is imported elsewhere

def test_wrong_patch(mock_call):
    pass

# Correct patch target - patch where used
@patch('myapp.views.call_api')  # Correct if 'call_api' is used in views

def test_correct_patch(mock_call):
    pass
📊

Quick Reference

Remember these tips when mocking in Django tests:

  • Use unittest.mock.patch to replace dependencies.
  • Patch the object where it is used, not where it is defined.
  • Use mock.return_value to set what the mock returns.
  • Assert calls with mock.assert_called_once() or similar.
  • Use context managers or decorators to auto-clean mocks.

Key Takeaways

Use unittest.mock.patch to replace parts of your code during Django tests.
Always patch the object where it is used, not where it is defined.
Set mock return values to control test behavior and avoid real side effects.
Assert mock calls to verify your code interacts correctly with dependencies.
Use decorators or context managers to ensure mocks are cleaned up after tests.