This is a library for building simple mock objects. Things are kept as simple as possible. The goal is to easily make mock functions and objects that can be used to stub out calls when doing unit tests.
The module provides a TestCase class that your test cases should inherit from, instead of inheriting from unittest.TestCase. The tinymock.TestCase class provides methods to create mock objects and mock functions, and checks at the end of each test that all of the expected calls were made to mock functions.
The simplest object to mock up is a function. Here is an example of calling a mock function that expects a single argument whose value is 1:
class TestIt(tinymock.TestCase):
def test_call_function(self):
fcn = self.mock_fcn("fcn").expect(1)
fcn(1)
The mock_fcn method in tinymock.TestCase creates a new mock function, and takes as its argument the name of the function. The expect tells the mock function to expect a call with the values that you are expecting the function to be called with. In the case above, the mock fuction is expecting a 1 to be passed in.
A return value can be specified by calling the returns method on the mock function object after a call. Here is an example that calls a function that expects no arguments and returns 2:
class TestIt(tinymock.TestCase):
def test_function_return(self):
fcn = self.mock_fcn('fcn').expect().returns(2)
self.assertEquals(2, fcn())
Upon creation, a MockFunction does not expect any calls. You use the expect method for each time you expect the method to be called. Here is a test case that directly calls a mock function three times, each time with different arguments and a different return value:
class TestIt(tinymock.TestCase):
def test_calls(self):
fcn = self.mock_fcn("fcn")
fcn..expect().returns(1)
fcn.expect("a").returns(2)
fcn.expect("b", "c").returns(3))
self.assertEquals(1, fcn())
self.assertEquals(2, fcn("a"))
self.assertEquals(3, fcn("b", "c"))
Making mock objects is straightforward. The MockObject class is simply a container for the members of the object, which can be set manually, or by passing in keyword arguments to the constructor. The mock_obj method in tinymock.TestCase creates new mock objects.
Here is an example that has an attribute a holding 1, and a mocked method b that returns 2:
class TestIt(tinymock.TestCase):
def test_object(self):
obj = self.mock_obj(
"my_object",
a = 1,
b = self.mock_fcn("obj.b")
)
obj.b.expect().returns(2)
self.assertEquals(1, obj.a)
self.assertEquals(2, obj.b())
Mock objects support mocking almost all built-in methods. The methods that are not supported are: __init__, __new__, __del__, __setattr__, __getattr__, and __getattribute__. For the rest, you can treat them just like normal functions:
class TestIt(tinymock.TestCase):
def test_add(self):
obj = self.mock_obj(
"my_object",
__add__ = self.mock_fcn('__add__')
)
obj.__add__.expect(1).returns(3)
self.assertEquals(3, obj + 1)
Because the pattern above is very common pattern, there’s a shorter way of saying it. The mock_obj method takes an optional parameter that is a list of methods to define, so the test above can be written like this:
- class TestIt(tinymock.TestCase):
- def test_add(self):
- obj = self.mock_obj(‘my_object’, [‘__add__’]) obj.__add__.expect(1).returns(3) self.assertEquals(3, obj + 1)
A patch can be used to replace a field in another module or object for the duration of a test. The patch method returns an object used as the context for a with statement to make the replacement, and then to restore things when the with statement is done. In this example, the sleep function is replaced with a mock function. This way the test can verfy that sleep was called, without having to wait:
class TestIt(tinymock.TestCase):
def test_sleeper(self):
sleep = self.mock_fcn("sleep").expect(10)
with self.patch(time, "sleep", sleep)
function_that_should_sleep_10_seconds()
If you have multiple calls to patch, you can use a PatchSet:
class TestIt(tinymock.TestCase):
def test_sleeper(self):
sleep = self.mock_fcn("sleep")
getpid = self.mock_fcn("getpid")
sleep.expect(10)
getpid.expect().returns(1)
patch_set = self.patch_set(
(time, "sleep", sleep),
(os, "getpid", getpid)
)
with patch_set:
function_that_should_sleep_10_seconds_and_getpid()
Subclass of unittest.TestCase that checks to make sure that all expected function calls have happened. If you use self.mock_fcn() and self.mock_obj() to make your mocks, then you don’t have to worry about calling check_done on them.
You do need to make sure that if you implement setUp() and tearDown() methods that you call super.
Make a new MockFunction. It’s check_done method will be called at the end of the test.
Make a new MockObject.
Convenience method to make Patch objects.
Convenience method to make PatchSet objects.
Get ready to make mock objects.
Make sure that all of the expected things happened.