A fast introduction to Mocking with Python

Hey there,

This post goal is to talk a little about Mocking, and how to do that (hopefully well) in Python. These are the main topics of this article, have fun!

  1. Are you mocking me, what is mock?
  2. Mocking use cases
  3. How to mock in Python?
  4. References

Are you mocking me, what is mock?

 

Mocking is basically to abstract some part of your code (function call, variable, API request, system call, …) and instead of calling the real thing, just pretend that it is there and it works correctly.

Why do you want this?

Mocking is mainly used in unit testing, why do we run unit tests? To be more confident that some particular and well-defined part of you code is working as it should. But what if part A of the code, that you’re interested in testing with unit tests, has a dependency with complex part B, you definitely don’t want the unit test testing the complex part B but mainly the part A, and complex part B will have its own unit tests, right? So how can we abstract complex part B? That’s right, Mocking it!!!

“In short, mocking is creating objects that simulate the behavior of real objects.” [2]

Mocking use cases

 

There’s a lot of valid use cases for Mocking, all of the ones I’ll say are related to unit tests because it is the mainly general use case for Mocking.

  • As I said in the last section, a good reason to mock a part of your code is in order to maintain unit tests isolated and concise. It’s not a good thing to have a unit test that tests a lot of things at once. You’re probably will prefer to break this big unit test in smaller ones, and mock can offer a cool way to do it!
  • Sometimes part of the code you want to test is just not working as it should (not ready yet, unstable, for some reason not available, failing), mocking in this case, is a good thing, because you can test the already stable part of the code.
  • To actually run some part of the code can be too costly or have some side effect not desired (API requests, create files, writing in files, system calls), so mocking can really help you test the code without worrying with these.
  • Test unpredictable code, good unit tests are always executed expecting the same values, random values can be mocked to avoid randomness in the unit tests.
  • Mock a certain complex object that you don’t really need to have it entirely, you can mock only the parts that interest you in the context.
  • And many more cases….

Important: Mocking is very powerful, but do it “the right way” is not that simple and involves practice and experience, a lot Mocking (especially bad mocking) can actually make your unit tests less effective.

How to mock in Python?

> Using the mock package [5].

Whatcan you do with the mock package?

 

  • Pretend to be anything you want!
import mock

anything = mock.Mock(return_value=3)
print anything() # 3

“Mock is a flexible mock object intended to replace the use of stubs and test doubles throughout your code”. The Mock Class can be used to repeat basically anything in the code, in the example above it represents s function that returns 3. Other useful things you can define for the Mock objects are:

  • “side_effect: A function to be called whenever the Mock is called. See theside_effect attribute. Useful for raising exceptions or dynamically changing return values. If side_effect is an iterable then each call to the mock will return the next value from the iterable.”

  • “return_value: The value returned when the mock is called. By default this is a new Mock (created on first access). “

  • “name: If the mock has a name then it will be used in the repr of the mock. This can be useful for debugging. The name is propagated to child mocks.”

An alternative for Mock Class is MagicMock, “MagicMock is a subclass of Mock with default implementations of most of the magic methods. You can use MagicMock without having to configure the magic methods yourself.”

  • Pretend to be a particular thing (object, function, call, …)
from mock import create_autospec

def any_function(a, b, c):
 pass

mock_function = create_autospec(any_function, return_value='unicorn')
print mock_function(1, 2, 3)
# returns 'unicorn'
mock_function.assert_called_once_with(1, 2, 3)
print mock_function('wrong arguments')
# error

“The mock.create_autospec method creates a functionally equivalent instance to the provided class. What this means, practically speaking, is that when the returned instance is interacted with, it will raise exceptions if used in illegal ways.”

from mock import patch

class SomeClass(object):
 def __init__(self):
 pass

@patch('__main__.SomeClass')
def function(mock_class):
 return mock_class is SomeClass

print function()

patch() as function decorator, creating the mock for you and passing it into the decorated function”. patch() will replace the class (or method) by a magicMock

 

References

 

[1] https://www.toptal.com/python/an-introduction-to-mocking-in-python

[2] http://stackoverflow.com/questions/2665812/what-is-mocking

[3] http://www.voidspace.org.uk/python/mock/mock.html

[4] https://docs.python.org/3/library/unittest.mock.html

[5] http://blog.thedigitalcatonline.com/blog/2016/03/06/python-mocks-a-gentle-introduction-part-1/#.WH9emXUrKkB

 

 

 

Advertisements
A fast introduction to Mocking with Python

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s