Are You Mocking Me?
00:00
In the previous lesson I gave an overview of the course. In this lesson, I’ll introduce you to the capital-M Mock class, which is key to dynamically faking code interactions.
00:12
In the overview, I mentioned that sometimes when testing your code, you don’t want all the code’s actions to happen. One way to deal with this is through the unittest.mock module, which contains tools to dynamically replace your real code with fake equivalents you can use and control in your tests.
00:29
The key mechanism to do this is the Mock class. Instances of this class dynamically create methods as you call them, meaning any method call you make on the class succeeds.
00:40
You can further configure Mock to control the response from these methods, allowing you to fake out any Python object. On top of that, there are also mechanisms for checking what got called.
00:51 This way, you can replace your code with a mock, have it succeed because any method call is allowed, then ensure that the code invoked those methods it was supposed to.
01:00 Let’s head to the REPL to learn more about mocking your code. Before faking out some code, let me just start by playing around with the mock object. I need to import it, and now I’ll instantiate it.
01:18
As I said before, you can call any method on a mock object and it will work. Calling say_hello() returns a new instance of a mock object which stores the fact that you called a method on it.
01:31
There’s nothing special about say_hello(). Any method I call will return a new instance with data about what has been called. Of course, a mock object is still a Python object, so I can assign values.
01:49 Note that this is different from what I was doing before. Here, I’m treating it like a regular Python object. You don’t typically do this, but if you need to add things to the object before it gets used by your code, you can.
02:01
Let me show you the difference. Now I’m going to use an attribute that doesn’t exist. This time, it works differently. Instead of getting back an assigned value, it returns a new Mock instance like it did with the method calls.
02:15 Alright, so you’ve got an object that will happily allow you to call anything on it. If you’re using such an object to help with your tests, it will stop your tests from calling the real thing and won’t fail.
02:26
But how will you know your code did what it was supposed to do? In addition to allowing you to call any method or access any attribute, Mock also tracks what you did with those methods and attributes.
02:38 You can then invoke assertions to see what happened.
02:43
This might seem a little funky if you’re not used to it, but everything in Python is an object, even method calls on an object. Of course you can call a method, but you can also treat it like data and associate things with it, like in this case, other methods. Here, the say_hello() method that I created by invoking it a minute before also has a child assertion method.
03:05
Notice that the REPL didn’t do anything here. Recall that an assertion that passes does nothing, which in this case is a good thing. If say_hello() hadn’t been called, then an exception would get raised.
03:17
Let’s do it again. There’s my second call to say_hello().
03:28
And there’s more than one assertion you can use. The assert_called_once() method asserts that a method only got called once. Since I called say_hello() twice, this assertion failed, resulting in the exception.
03:41 The exception even tells you that the error happened because the method got called twice. Likewise, if I check for something I never called,
03:54
I get an AssertionError here as well. This tells me that did_not() was not called at all. To go along with checking something did get called,
04:08 there are also methods to check that something did not get called. Let me call something new, this time with an argument.
04:24 and a new variation on the assertion: this time, checking that the method got invoked with a specific argument,
04:36 which of course fails if I assert the call with a different argument. To go along with the assertions, there is also data you can access on the mock to see what happened.
04:49
As you might guess, the .call_count attribute stores how many times something got invoked.
04:57
The .call_args attribute shows you what argument got used during the last call. While .call_args_list shows you all of the calls, which in this case was just the one.
05:11
So far, the attributes I’ve been showing you are the ones on the newly created method. If you go up to the object itself, the .method_calls attribute shows you all the methods that have been invoked on the object, including their arguments.
05:26 Now that you’ve got the idea, in the next lesson, I’ll show you where you might use a mock object in your code.
Become a Member to join the conversation.
