To do that you can mock the class function with the @patch like that
from mock import patch
# Our class to test
class FooObject():
def update(self, obj):
print obj
# Mock the update method
@patch.object(FooObject, 'update')
def test(mock1):
# test that the update method is actually mocked
assert FooObject.update is mock1
foo = FooObject()
foo.update('foo')
return mock1
# Test if the mocked update method was called with 'foo' parameter
mock1 = test()
mock1.assert_called_once_with('foo')
You can even mock more functions like that:
from mock import patch
class FooObject():
def update(self, obj):
print obj
def restore(self, obj):
print obj
@patch.object(FooObject, 'restore')
@patch.object(FooObject, 'update')
def test(mock1, mock2):
assert FooObject.update is mock1
assert FooObject.restore is mock2
foo = FooObject()
foo.update('foo')
foo.restore('bar')
return mock1, mock2
mock1, mock2 = test()
mock1.assert_called_once_with('foo')
mock2.assert_called_once_with('bar')
Answer from Tim Rijavec on Stack OverflowIn the end I used Python's mock, which allows me to override complicated_function without having to adjust the original code in any way.
Here is the original script, and note that complicated_function is not passed in to my_loopy_function as an 'action_function' parameter (which was what I tried in my earlier solutions):
// my_script.py
def my_loopy_function():
aggregate_value = 0
for x in range(10):
aggregate_value = aggregate_value + complicated_function(x)
return aggregate_value
def complicated_function(x):
a = do()
b = something()
c = complicated()
return a + b + c
and here is the script I am using to test it:
// test_my_script.py
import unittest
import mock
from my_script import my_loopy_function
class TestMyModule(unittest.TestCase):
@mock.patch('my_script.complicated_function')
def test_1(self, mocked):
mocked.return_value = 1
self.assertEqual(10, my_loopy_function())
This works just as I had wanted:
- I am able to substitute functions with a simpler version of themselves that I can more easily test,
- I do not need to alter my original code in any way (such as I was trying -- which was effectively by passing in function pointers), the
mockmodule gives me post-coding access to the innards.
Thanks to austin for his suggestion to use mock.
BTW I am using Python 2.7 and therefore used the pip-installable mock from PyPI.
Don't try to override complicated_function with action_function, just use complicated_function as the default action_function:
def my_loopy_function(action_function=complicated_function):
aggregate_value = 0
for x in range(10):
aggregate_value = aggregate_value + action_function(x)
return aggregate_value
Yes! You can leverage the setUp/tearDown methods of the unittest.TestCase and the fact that unittest.mock.patch in its "pure" form (i.e. not as context manager or decorator) returns a "patcher" object that has start/stop methods to control when exactly it should do its magic.
You can call on the patcher to start inside setUp and to stop inside tearDown and if you keep a reference to it in an attribute of your test case, you can easily stop it manually in selected test methods. Here is a full working example:
from unittest import TestCase
from unittest.mock import patch
class Foo:
@staticmethod
def bar() -> int:
return 1
class TestMyThing(TestCase):
def setUp(self) -> None:
self.foo_bar_patcher = patch.object(Foo, "bar", return_value=42)
self.mock_foo_bar = self.foo_bar_patcher.start()
super().setUp()
def tearDown(self) -> None:
self.foo_bar_patcher.stop()
super().tearDown()
def test_a(self):
self.assertEqual(42, Foo.bar())
def test_b(self):
self.assertEqual(42, Foo.bar())
def test_c(self):
self.assertEqual(42, Foo.bar())
def test_d(self):
self.foo_bar_patcher.stop()
self.assertEqual(1, Foo.bar())
This patching behavior is the same, regardless of the different variations like patch.object (which I used here), patch.multiple etc.
Note that for this example it is not necessary to keep a reference to the actual MagicMock instance generated by the patcher in an attribute, like I did with mock_foo_bar. I just usually do that because I often want to check something against the mock instance in my test methods.
It is worth mentioning that you can also use setUpClass/tearDownClass for this, but then you need to be careful with re-starting the patch, if you stop it because those methods are (as the name implies) only called once for each test case, whereas setUp/tearDown are called once before/after each test method.
PS: The default implementations of setUp/tearDown on TestCase do nothing, but it is still good practice IMO to make a habit of calling the superclass' method, unless you deliberately want to omit that call.
While accepted answer is perfectly fine, I'd go for approach which keeps decorator for the class and uses context managers for methods in which you want to override a mock, see sample code below:
@mock.patch("foo", bar)
class TestMyThing(TestCase):
def test_A(self):
assert something
def test_B(self):
assert something
def test_C(self):
assert something
def test_D(self):
with patch('foo', baz):
assert something
This achieves your goal, as context manager mock is applied inside of a test function, so it happens after applying the class decorator mock and therefore it effectively overrides class decorator mock. Also, I think it's simpler and it requires less code, especially if you have no other reason to implement setUp() and tearDown() methods.
You can't mock a function's local variable. To make your code easier to test, change it to, e.g:
def keep_trying(self, timeout=300):
end_time = time.time() + timeout
# etc, as above
so it becomes trivial for tests to run it with a shorter timeout!
Rather than trying to mock the value if timeout, you'll want to mock the return value of time.time().
e.g.
@patch.object(time, 'time')
def test_keep_trying(self, mock_time):
mock_time.side_effect = iter([100, 200, 300, 400, 500, 600, 700, 800])
...
Now the first time time.time() is called, you'll get the value of 100, so it should timeout when after a few turns of your while loop. You can also mock time.sleep and just count how many times it gets called to make sure that part of the code is working properly.
Another approach (which isn't completely orthogonal to the one above) is to allow the user to pass an optional timeout keyword to the function:
def keep_trying(self, timeout=300):
...
This allows you to specify whatever timeout you want in the tests (and in future code which doesn't want to wait 5 minutes ;-).
Here is a simple way to do it using mock
import mock
def new_loaddata(cls, *args, **kwargs):
# Your custom testing override
return 1
def test_SomeProductionProcess():
with mock.patch.object(SomeProductionProcess, 'loaddata', new=new_loaddata):
obj = SomeProductionProcess()
obj.loaddata() # This will call your mock method
I'd recommend using pytest instead of the unittest module if you're able. It makes your test code a lot cleaner and reduces a lot of the boilerplate you get with unittest.TestCase-style tests.
To easily mock out a class method with a structured return_value, can use unittest.mock.Mock.
from unittest.mock import Mock
mockObject = SomeProductionProcess
mockObject.loaddata = Mock(return_value=True)
EDIT:
Since you want to mock out the method with a custom implementation, you could just create a custom mock method object and swap out the original method at testing runtime.
def custom_method(*args, **kwargs):
# do custom implementation
SomeProductionProcess.loaddata = custom_method