Skip to content

Instantly share code, notes, and snippets.

@evansde77
Last active September 9, 2020 15:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save evansde77/215a70619e55cecacdde917f16a33587 to your computer and use it in GitHub Desktop.
Save evansde77/215a70619e55cecacdde917f16a33587 to your computer and use it in GitHub Desktop.
examples of performing mock.patch actions in three different but equivalent ways
#!/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