Understanding Unittest.Mock

Mocks in pytest

Your browser needs to be JavaScript capable to view this video

Try reloading this page, or reviewing your browser settings

Examples of how to combine mocks in pytest and common pitfalls when patching and using fixtures in the same test scenario.

Keywords

  • mock
  • pytest
  • pitfalls
  • patching
  • fixtures
  • test

About this video

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

Video Transcript

In this segment, we’re going to see some peculiarities of combining mock with pytest. We’ll see what happens when we try to use patch as decorator and we use fixtures as well. And we’ll see how to create some fixtures that, uh, allow us to mock and patch some internal resources or create some mock that are already predefined behavior for us. Let’s see how pytest can work with mock. Because even if, uh, pytest has its own version of mock, uh, for mock patching, um, it… uh, it’s quite often to see, uh, that our test that run… are created just with, um, unittest.mock and we use pytest just… as a way to run the test. So first of all, we have this file, which basically combines fixture and the mock. We can see here that, uh, you know, we have this test, well, like, first word saying that whatever, like, when we are just using normal test, everything should work, but there are some combinations that can be surprising for the user. So here I said, we have this test, right, um, that has fixture and the mock, right. And as we know in pytest, uh, we just not… we just… we just pass the fixtures… the fixtures as, uh, we just put it here in the argument so this fixtures would call this one. Most people will just, you know, add the patch and they have this, uh, this blindly rule in the brain as we saw in the previous segment that, uh, one of the other patches put the new, mock that’s been created at the end. Now, uh, if you’re trying to run those, let’s see, this is going to fail. And this is going to fail because it says it’s not able to find the… a fixture called mock. And the problem… the problem that’s happening here… and, you know, you’ll see in many places with different kinds of person that they say that, uh, pytest doesn’t support, uh, um, patching because of this. But it should… but that’s far from the truth. The problem here is that the way that, you know, the way that the mock patches is working, is that when you do… when we do the patches adding the argument to it, right. And now the second part of it is like once that’s resolved, so basically when we have this function and this one is returned up to see it in a way, you’re going to have, um, the first argument being filled by patch. And then with the arguments that we don’t fill when this thing is called, okay, when this is… thing’s called, this patch is going to generate one. This is going to fill the last one that’s not being used. So it’s going to be this one, right. And then, um, pytest is going to try to find the rest of them and try to see if they can match it to fixtures. So that’s why when we add, um, uh, patch… well, when we patch a tests and we use decorators, yes, we need to add them in reverse order so therefore appending at the end, but fixtures won’t be satisfied by, um, any argument, right. They need to go at the end. So that means that we… let’s go to file. That means that our fixture needs to go by the end. So if we do mock, that we save this file. Just cut it again. Yeah. And now, you know, we have to patch and this fixture argument will never be, like, fulfilled by any of the patches. And pytest will fill it with some fixture as you can see and now that passes. So this is probably same people not using the decorator on tests just because they don’t understand how that works. So if you have mock… more fixtures, you can have them, you know, just always after all the mocks have been, uh, fulfilled. So if you have more mocks, let’s say we have mock one then we have, uh, another mock which is going to patch, um, I don’t know, like, um, any other thing here like as we used to do, request… let’s just say request.session then, you know, he will have, uh, request_mock, right because it goes at the end. So we append the patches because they are going in reverse orderand then we should just patch the fixtures. We have fixture2. It doesn’t matter if it goes here or here where the key is like, first you do all the mocks then you do the fixtures. And the mocks needs to go… you can think of it as in reverse order with the time you patch it. Now the only thing I really like about pytest and these fixtures, um, that I think goes really well with, uh, mock and pytest, that you can create what’s known as, uh, you know, as a mock fixture. So basically this is going to be a fixture that’s going to allow us to, you know, mock some resource or something else. So let’s see for example, we have a file where you’re doing this, which is called test_mock_fixture.py. Now all this file has is basically a fixture, okay. This is pytest fixture. And then within the fixture, we have, uh, this. And this is basically, um, this is a fixture that’s going to configure among, it’s going to yield it so you can still use it, but it’s going to have… because we yield it and we don’t return, it’s really important you don’t return here, you want to yield it, so the, you know, like this function doesn’t finish here, but it’s going to execute our test then come back and then exit the context manager. If you yield it, all your tests, by just declaring the fixture here are going to be used within this fixture. What this means is that here, we are fake… uh, we are patching os.system and we can, for example, configure expected behavior for the mock there, which I think is really useful. So with this, we can just run our test and there we go. And we can see that it’s returning, nope. Andall we have done you know we don’t have to use the patch or any of the,eh, we did not have to use mock patch or do anything here. All we are doing is we are depending on this fixture that is effectively setting mock for us and is setting the expectations… well, is setting what we expect the mock to return for us which is, I think, is really powerful because you can combine multiple mocks and how, for example, let’s say you have a bunch of tests that are going to test, uh, against the GitHub API, you can just have this fixture and, you know, just use it in all the test. You can even have auto use from pytest to have it automatically used, uh, in all the tests. If you want that as well, you can… you know because we are yield… if we wanted to see fire at configuring the test, you could also make this yield, return the mock itself, and that way you can even configure it in this test, which is, again, really powerful. That’s kind of the mainly two things to be aware when combining pytest with mock. Everything else should be just as expected.