Understanding Unittest.Mock

Mocking Internal Dependencies

Your browser needs to be JavaScript capable to view this video

Try reloading this page, or reviewing your browser settings

An overview of how our Python code can have internal dependencies that make it hard to test and how we can use the patch function to replace them.

Keywords

  • Patch
  • existing objects
  • open function
  • dynamic value
  • decorator
  • pitfalls

About this video

Author(s)
Mario Corchero
First online
25 December 2018
DOI
https://doi.org/10.1007/978-1-4842-4413-5_7
Online ISBN
978-1-4842-4413-5
Publisher
Apress
Copyright information
© Mario Corchero 2019

Video Transcript

In this segment we’re going to see mocking internal dependencies. So basically what happens when we have internal dependencies and internal inputs, we understand what they are, and how can you use unittest.mock.patch to remove them and to make them behave as we want. Let’s see how can we isolate ourselves from dependencies that are known as internal dependency, which are basically dependencies that we don’t have control as a user. But the mock library allow us to patch them as we’re going to see them which is basically replacing them our runtime. Okay. So first of all, we have this file called source_code.py, which have this function go, uh, get_username. We’ve seen this before, it’s basically the same thing, but rather than having requests.session being passing this argument, now this session is something that the function is greater within it. This is not quite often am because sometimes that’s why the code is not thought to make it easier to test all because sometimes they just want to encapsulate all dependencies within the function. Okay. So in this situation, if we were to run this code, all we had to do was… would be import the source code, right, and then source_code.get_user_name (“m ariocj89”). And that’s… uh, it’s going to go to GitHub which is what we want to change, right. We want to make sure we are hitting, uh, testing double and therefore we have control over that indirect input that his function is having. Okay. So I said we can do, uh, we can input from unittest.mock and function called patch. Also we’re also going to bring seal, uh, that we saw before for the sake of, uh, showing in unittest. And then we’re going to say this is the payload with, like, uh, testing double to return, right, we said for example it’s going to be “secret user”. We like that request session when it’s called get and then JSON, we’d like it to return this rather than going to GitHub and, you know, which effectively means going over the network and retrieving the real thing. Okay. So we’re going to say… we can use, uh, patch to do this in the… in the following way. We can do with patch as a context manager request.session. Sorry, this has to go within the string and as mock. Okay. Now we’re going to say mock.get.return_value, same thing as before, right, .json.return_value = payload. Sometimes it’s important if you are seeing… this is really important… is key that you see in the next segment as well because just to simplify the explanation, we’re going to make some things like I’m going to write the code in such a way that’s easy to understand for the… for this first segment, but this key that you see the next segment as well because I’m going to show some of the useful mistakes people make and that I’m making here again for the sake of explaining it easier. But this is… this is something that… well it happened quite often and you might… you might not have noticed this here, but this is not going to work. And the reason why this is not going to work, if we are now to call again the function, right. And we run it. And we’re going to get requests doesn’t have… oh, sorry, it’s not sessions. Its session. There you go. And the reason that it’s not work is we’re going to get… we’re going to get this MagicMock back which is not what we expected, right. If we use seal here, because we know we want to… it seems that when we are calling this, there’s still like these, automatic creation of childs happening which we don’t want, right. We is justoneway to create the child here to define the… how the mock looks like. So if we pass seal to it, we’re going to see, um, that, you know, session.return_value hasn’t been defined. This is a common, uh, misunderstanding of people using mock and patch. The thing is like because we are patching requests.session which is request.sessions, we forget that this is class and this is going to be called as you can see here. So what we have created here in these .get.return_value.json. This is on the class level and that’s not what we want. We want that, you know, a class has to return something to create an instance and then we do the rest. So for this to work, what do we need to do is we need to call .return_value here. Okay. So now this mock.returnt_value is going to be the class constructor that’s going to return this in instance, right, so here we have an instance of a session, then we have when we called get on the session is going to return an object that when we called JSON on the object is going to return the payload. Now this is going to work. And that’s great. And as you can see, seal was key to understand what’s going on, right? Because see if we go back to the error, seal is telling us like “Hey, you have not defined seal.return_value. This is you get like a MagicMock, right. And we are lucky that we get it by with sometimes, you might not even get the object back. So by using seal, we’re able to see they are much easier. Now with this, we now have the code that is effectively patching this internal dependency which is this requests.session and, uh, then it’s returning whatever we want them to return, so it can be secret. You know, we can change the… uh, we can change the same direct input or whatever we want, it’s going to change. This is a great way to make our function which is this get_user_name not depend on external resources like for example the network because we don’t want our tests as we explain the first segment to depend, uh, in unreliable things, in things that we are… we cannot trust, right, because, um, the real GitHub can change at any point. It also makes mistakes lower. It’s not the way we should… we are… we should be doing unittests.