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

 

 

 

A fast introduction to Mocking with Python

Hey, How is Outreachy going?

Hey there!

First of all sorry for the absent time without writing on the blog (especially not writing about Outreachy), but anyway… Happy 2017, and we’re back on track!

So, the last Outreachy post was about how to run a MapReduce job using DevStack and different types of data sources as input and output. In this article, I’m gonna talk a little about the things I’ve done until now in this internship and what I’m currently doing.

As I said before,  my internship project is to refactor some data source/job binary related code in order to create a clean abstraction that will allow new developers to implement new data source types and job binary types more easily. So, how are things until now?

  1. My first task was to learn a little more about stevedore and how Sahara uses it
  2. Then I’ve set up the DevStack environment in order to run MapReduce jobs and to learn how to do that with multiple types of data source (just in order to understand how the final user does it)
  3. One of the major tasks I had to do was to create the abstraction itself, it demanded a lot of coding reading and grepping code all over the Sahara repository. The result of this task was the creation of the spec and blueprint of the project. These are still being improved accordingly with task 4.
  4. Develop the abstraction and the data source/job binary types implementation, and of course, refactor the code in order to adapt for these abstractions. This is what I’m currently working on and the code can be seen here.

I hope this post was helpful somehow, and have a nice day!

Hey, How is Outreachy going?