Note that using a mock doesn't necessarily imply using a mocking library. It can be easy enough to write your own. The basic idea is this: the thing you use in your production code has a particular interface (i.e. methods you can call on it with their defined signatures, set of possible return values and exceptions they can throw) and then a mock is simply another implementation of the same interface but one that's totally under your control.
Let's say I have a function to display some kind of rate (a tax rate or whatever else) and that rate is different in the morning and afternoon. I want to test that the correct string is output. I might write a test like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import unittest
from display_rate import display_rate
class MockOutputStream( object ):
written = ""
@staticmethod
def write(value):
MockOutputStream.written + = value
MockOutputStream.written + = "\n"
class TestDisplayRate(unittest.TestCase):
def test_morning_rate_is_displayed( self ):
hour_of_day = 6
display_rate(hour_of_day, MockOutputStream.write)
self .assertEquals(MockOutputStream.written, "The morning rate is 5%\n" )
if __name__ = = '__main__' :
unittest.main()
|
where the implementation might look like
1 2 3 4 5 6 7 8 9 |
def display_rate(hour_of_day, write):
if hour_of_day < 12 :
rate = 5
when = "morning"
else :
rate = 8
when = "afternoon"
write( "The {} rate is {}%" . format (when, rate))
|
The second argument to
display_rate
is a function for writing the output somewhere - in the test, it just writes to a variable called
written
in
MockOutputStream
and in production code, I might pass the
print
function so that output is written to standard out. They both conform to the same interface (a function that takes a value and returns
None
).
In the last couple days at work, two of us ended up writing our own simple mock in Lua. We aren't Lua experts on my team (we're a Scala team), but we needed to write in Lua because that's the language you can program in for NGINX. We do TDD and so wanted to write a test for a component we needed to implement that had to make a call to a remote service and return a value depending on the response. So, our unit tests just used a mocked version of the client so that we could test all our cases (success and various failures) and it was very lightweight - no need to go to the effort of figuring out how to use a library and it wouldn't have given us any real advantage even if we had.