Last active
September 9, 2020 15:21
-
-
Save evansde77/215a70619e55cecacdde917f16a33587 to your computer and use it in GitHub Desktop.
examples of performing mock.patch actions in three different but equivalent ways
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
mock examples | |
""" | |
import os | |
import unittest | |
import mock | |
import functools | |
def test_this_function(path): | |
""" | |
this is the function we are going to | |
test and mock out the call to os.path | |
""" | |
return os.path.exists(path) | |
def example_decorator(func): | |
print("example_decorator.decorating:{}".format(func)) | |
@functools.wraps(func) | |
def wrapper(func, *args, **kwargs): | |
patcher = mock.patch('os.path.exists') | |
print("example_decorator.patcher.start") | |
mock_exists = patcher.start() | |
result = func(mock_exists, *args, **kwargs) | |
print("example_decorator.patcher.stop") | |
patcher.stop() | |
return wrapper | |
class ExampleTest(unittest.TestCase): | |
""" | |
this test shows examples of using | |
mock.patch as a decorator and a context | |
Note that both mocks perform the same function | |
""" | |
def test_with_context(self): | |
""" | |
in this test we mock os.path.exists using | |
mock.patch as a context | |
""" | |
print("{}.test_with_context".format(type(self).__name__)) | |
with mock.patch("os.path.exists") as mock_exists: | |
mock_exists.return_value = True | |
# within this statement, the mock is in effect | |
result = test_this_function("PATH") | |
self.failUnless(result) | |
self.failUnless(mock_exists.called) | |
mock_exists.assert_has_calls([mock.call('PATH')]) | |
# outside of context, the mock is not in effect | |
# and we call the real os.path.exists | |
result = test_this_function("PATH") | |
self.failUnless(not result) # file ./PATH shouldnt exist | |
@mock.patch('os.path.exists') | |
def test_with_decorator(self, mock_exists): | |
""" | |
in this test we again mock os.path.exists | |
but use mock.patch as a decorator that fires | |
before the function is called and cleans up | |
after the function finishes | |
""" | |
print("{}.test_with_decorator".format(type(self).__name__)) | |
mock_exists.return_value = True | |
result = test_this_function("PATH") | |
self.failUnless(result) | |
self.failUnless(mock_exists.called) | |
mock_exists.assert_has_calls([mock.call('PATH')]) | |
class ExampleSetupTest(unittest.TestCase): | |
""" | |
this example uses mock.patch during the setup and | |
tear down of the test. | |
This approach is useful for applying repeated | |
mocks to all tests in the class | |
""" | |
def setUp(self): | |
""" | |
set up for tests by creating the mock and | |
starting the patcher | |
""" | |
print("{}.setUp".format(type(self).__name__)) | |
self.patcher = mock.patch('os.path.exists') | |
self.mock_exists = self.patcher.start() | |
def tearDown(self): | |
""" | |
the tearDown method stops the patcher after | |
the test function has run | |
""" | |
print("{}.tearDown".format(type(self).__name__)) | |
self.patcher.stop() | |
def test_with_true(self): | |
""" | |
test with the mock returning True | |
""" | |
print("{}.test_with_true".format(type(self).__name__)) | |
self.mock_exists.return_value = True | |
result = test_this_function("PATH") | |
self.failUnless(result) | |
self.failUnless(self.mock_exists.called) | |
self.mock_exists.assert_has_calls([mock.call('PATH')]) | |
def test_with_false(self): | |
""" | |
test with the mock returning False | |
""" | |
print("{}.test_with_false".format(type(self).__name__)) | |
self.mock_exists.return_value = False | |
result = test_this_function("PATH") | |
self.failUnless(not result) | |
self.failUnless(self.mock_exists.called) | |
self.mock_exists.assert_has_calls([mock.call('PATH')]) | |
class DecoratorExampleTest(unittest.TestCase): | |
""" | |
test case that uses example decorator to illustrate the | |
program flow via the decorator approach | |
""" | |
@example_decorator | |
def test_example_decorator(self, mock_exists): | |
""" | |
this is identical to using @mock.patch | |
but more illustrative of what @mock.patch is doing | |
""" | |
print("{}.test_example_decorator start".format(type(self).__name__)) | |
mock_exists.return_value = False | |
result = test_this_function("PATH") | |
self.failUnless(not result) | |
self.failUnless(mock_exists.called) | |
mock_exists.assert_has_calls([mock.call('PATH')]) | |
print("{}.test_example_decorator end".format(type(self).__name__)) | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment