Understanding Unittest.Mock

Other Ways to Patch

Your browser needs to be JavaScript capable to view this video

Try reloading this page, or reviewing your browser settings

How to patch existing objects, the open function, dynamic values, using it as a decorator (and its pitfalls) etc.

Keywords

  • patch
  • open
  • function
  • dynamic values
  • 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_10
Online ISBN
978-1-4842-4413-5
Publisher
Apress
Copyright information
© Mario Corchero 2019

Video Transcript

In this segment, we’re going to see other ways to patch. We’ll see how to manually start and stop, uh, our patchers and also how to do it by using decorators. Sometimes we want further control when we are patching objects and we can do this by manually deciding when to start and when to stop that. Let’s see an example. If we bring again patch and we have again this import source_code2, right. This function as we saw before has a method called, um, get_user_name that’s going to return you to get the username for GitHub. No, we don’t want the original username. We want to fake, um, so we want that payload return is that and what we are going to do is we’re going to create a patcher by just calling patch on it without the context manager. And this is source_code2.Session. Okay. So this is going to give us a patcher that now we can interact with. And when we call patcher.start, this is going to return you the bulk the same way when we were using this context manager. Now we can tell mock.return_value because we need to create a session .get.return_value again .json.return_value and this is going to give us… this should return always the payload, right, the payload that we wanted to make a return. Okay. Now, uh, because we called start we have that, if we now call, source_code2.get_user_name(“ mariocj89”) for example, and we can see here that’s also called patcher.stop this is going to finish the patching, so basically this start and this stop access the context manager that we saw before. And when we call this, this is going to generate the same effect and it’s going to produce, uh, if we want to print it out, right. So this is Secret payload it’s called secret user, right. And as we can see now, we have full control on this… on what… what’s this code will want the patch to be happening. You can see that we can stop here if we were to call stop. One line above. The patch has the… has been… the patching has been stop earlier and effectively this get_use_name is not going to the… to GitHub. So with just calling start and stop, uh, when we do patch, we can control what’s the area where we want to do it. We can even, you know, have some kind of a callback that will do it or become as creative as we want but this is just a different way to patch, uh, our internal dependencies. It some situations, we might be writing tests and from we learn we might be tempted to just use this context management, right. But there’s a simpler way to do it and it’s by using patch, um, as a decorator. So instead of doing this, we want to do patch decorator. We can just take this code, so, you know, this code works, right. But if we wanted to use this as decorator, then we can do the following. We can do… well, we take this code here, right. And we can just use this as decorator. And now this mock goes as an argument to the function. So if we run the same thing, this is the same. And it’s almost the same because the only difference is now that this patch, uh, is happening in the whole… for the whole function whilst here was only happening for this last two. There’s something to be aware of but most of the cases final. When we create our tests, we can just the decorate them and just run them, which is to be fair, much cleaner and much nicer to see and to read. But the something we need to be aware of is that what this patch is doing is basically taking this function getting all the arguments that it has and then adding it to the beginning. Reason why I say this is because like, one of the… you know again, one of the main, um, like at traps that people fall in it when using, uh, patch, is when they need to patch multiple things. Let’s say that we also want to patch, um, if we are not going to use it going to use it for some reason, we want to pass os.system. Now when we write this for the first time, we might think that, you know, the first… the first one is going to be mock_system, the second one is going to be mock_session, right. These are really far from the truth. We h are back to our situation where, um, this mock_session, uh, wasn’t created. And the reasoning is that because as we said, the arguments are adding at the end, what’s happening is that if we go back here, and we’ll say this is mock_session, now going to have the other one. We have the function like that, right? If you now add one more patch as we just did, os.system, this decorator is this is going to get the output of this, okay, and add one more argument. So when it adds the argument, it adds it at the end. So effectively the os or the system, the mock_system goes here. And, you know, the mock_session is what… is here. And we need to understand, we need to remember how this patch… or how this patch decorator works, how basically decorators work in general your own, because the order of the arguments is the reverse order of the… of the… of decorators. This is because I said, it’s just taken the function another one more argument add to it. So just remember whenever you are using patches or decorator, make sure that the… the arguments that you are… you are passing, like, well, the mocks that you are passing it as a result of the patches, need to be in reverse order of the way you are patching them. You can just say this as being reverse order you know. This session is the first one, the system is second one, then we’ll add the third one here, it will go out and this is because, you know, you can go from… you can see these layers.