When writing unit tests in Python, you'll often want to patch an entire class. In my case, I've got a function that initializes a class, and that class needs to be patched in its entirety.

Note: This example will be used throughout this guide.

I want to test a function called add_numbers :

from utils import Slack def add_numbers(x, y): try: result = x + y except TypeError: result = 'Could not add: {0} and {1}'.format(x, y) slack = Slack() slack.send(result)

Basically it's a function that adds two numbers, and sends the response to a slack channel via an API request. That API request is handled through another class called Slack (located in utils.py ):

import json import requests SLACK_HOOK = 'https://hooks.slack.com/services/ab/cd/ef' class Slack: def __init__(self, *args, **kwargs): # Use the hook_url pass or default to SLACK_HOOK self.hook_url = kwargs.get('hook_url', SLACK_HOOK) def send(self, msg): headers = {'Content-type': 'application/json'} payload = {'text': msg} requests.post( self.hook_url, data=json.dumps(payload), headers=headers, )

When unit testing, we want to test the smallest pieces of application code in isolation. And even more importantly, we don't want to write unit tests that fire off API requests to outside services. So, we'll want to patch the Slack class when writing unit tests for the add_numbers function.

So here is how we patch the Slack class for this test.

import unittest from add_numbers import add_numbers from unittest import mock, TestCase class TestAddNumbers(TestCase): @mock.patch('add_numbers.Slack') def test_calls_slack_send(self, mock_slack): _slack = mock_slack.return_value add_numbers(1, 2) # Assert send called self.assertEqual(_slack.send.call_count, 1) if __name__ == '__main__': unittest.main()

From here on, I'll exclude the imports and the call to our test runner.

What I want to point out about this example is how the Slack class is patched.

First, the patch decorator is used. If you're a keen observer, you'll notice we're patching add_numbers.Slack as opposed to utils.Slack (where the class actually lives). We'll discuss this in a later step.