Beesbot

Python Test Case Mocking

Mar 14, 2018

The way to mock in a Python TestCase without tons of nesting and with the flexibility to test success, failures and exceptions. Start by just mocking a method called in your view

from django.test import TestCase
from mock import patch

class AppTests(TestCase):

    def setUp(self):

        my_method_patch = patch('app.views.MyClass.my_method', return_value={
            success: True
        })
        self.addCleanup(my_method_patch.stop)
        self.my_method_mock = my_method_patch.start()

        return None

    def test_view_method(self):

        # 200?
        response = self.client.get("/")
        self.assertEqual(response.status_code, 200)

        # method called
        assert self.my_method_mock.call_count == 1

In another test you want to override the return_value, no problem

    def test_view_method_override(self):

        # override and make it fail
        with patch('app.views.MyClass') as mock:
            mock.my_method.return_value = { 'success': False }

        # 200?
        response = self.client.get("/")
        self.assertEqual(response.status_code, 200)

You know that thing is going to blow up some day, test that out too?

    def test_view_method_exception(self):

        # override and make it fail
        with patch('app.views.MyClass') as mock:
            mock.my_method.side_effect = Exception('error on purpose')

            # 500
            response = self.client.get("/")
            self.assertEqual(response.status_code, 500)
            self.assertTrue('error on purpose' in context.exception)

Great if you got a class that wraps a 3rd party api, some integration code that isn't under your control, etc.