The following examples all use the Python Mock library. This post is intended as a quick “Getting Started” for someone who is new to using Python Mock. For more advanced usages you can refer to the Python Mock Documentation.
You can download the code from GitHub here. (Follow the instructions in the Readme)
You will need to install the mock library:
pip install -U mock
Here is the code we will use as our “code under test” to write these example tests. You can put this code in a file called my_module.py:
class MyClass(): def my_method(self): pass class SomeOtherClass(): def method_under_test(self): myclass = MyClass() return myclass.my_method()
In our Tests we will be testing class SomeOtherClass and method method_under_test and mocking the class MyClass as well as mocking the method my_method.
Your test file will need the following import statements:
import unittest from my_module import MyClass, SomeOtherClass from mock import patch, Mock
To mock a method in a class to return a specific value use @patch.object.
@patch.object(MyClass, 'my_method') def test_shouldReturnValue_whenMethodIsMocked(self, mock_my_method): # Arrange mock_my_method.return_value = True some_other_class = SomeOtherClass() # Act result = some_other_class.method_under_test() # Assert self.assertTrue(result)
To mock an entire class to test interactions with that class use @patch.
@patch('my_module.MyClass') def test_shouldRecordMethodWasCalled_whenClassIsMocked(self, mock_my_class): # Arrange some_other_class = SomeOtherClass() # Act some_other_class.method_under_test() # Assert self.assertTrue(mock_my_class.called)
To mock an entire class with @patch and still set the return value of a method in that class, grab the instance of the mock object’s return value and set the method’s return value on the instance. There is a section on the patch page explaining how to do this.
@patch('my_module.MyClass') def test_shouldReturnValue_whenReturnValueIsSetOnMethodOfMockedClass(self, mock_my_class): # Arrange mc = mock_my_class.return_value mc.my_method.return_value = True some_other_class = SomeOtherClass() # Act result = some_other_class.method_under_test() # Assert self.assertTrue(result)
To mock a method in a class with @patch.object but return a different value each time it is called, use side_effect. Side effect allows you to define a custom method and have that method called each time your mock method is called. The value returned from this method will be used as the return value your mock method.
@patch.object(MyClass, 'my_method') def test_shouldReturnANewValueEachTime_whenMethodIsMockedUsingSideEffect(self, mock_my_method): # Arrange list_of_return_values = [True, False, False] def side_effect(): return list_of_return_values.pop() mock_my_method.side_effect = side_effect some_other_class = SomeOtherClass() # Act result_one = some_other_class.method_under_test() result_two = some_other_class.method_under_test() result_three = some_other_class.method_under_test() # Assert self.assertFalse(result_one) self.assertFalse(result_two) self.assertTrue(result_three)
Run The Tests
To run the tests, put the imports and tests into a file called tests.py in a class called SomeOtherClassTest.
You can then run the tests with the following command:
python -m unittest tests.SomeOtherClassTest
You will see the output:
Ran 4 tests in 0.005s OK
There are many other features in the Python Mock library, but these are the basics that will help you get started!
I hope that helps!