patch.object() as Context Manager
00:00
Now, what if you don’t want to mock an entire module, but you only want to mock a particular object within that module? Well, fortunately, we have a function called patch.object()
to do exactly that.
00:15
patch.object()
can be used as a context manager or a decorator just as patch()
can. Let me show you what that looks like. So it’s basically the same thing here, except that this argument is no longer the path to the object that you want to mock—it needs to be the object itself.
00:35
So when we do patch.object()
—it’s with patch.object()
—the first argument is the actual object that we want to patch, not the path to it.
00:48
So this needs to be requests
and we want to patch requests.get()
, and that is coming from my_calendar.py
. So again, just higher level, remember that we’re testing get_holidays()
, and get_holidays()
uses requests.get()
.
01:07
We want to patch this .get()
method, not the entire requests
module. One way we can do that here in our tests.py
is say from my_calendar import requests
.
01:23 That way, we have this object
01:28
and we can use it as the first argument here to patch.object()
. Then the second argument is the object that we want to patch. We’ve brought in this requests
module and we want to patch 'get'
, and this is a string. And then we can set the attributes, the Mock
object attributes that we are now familiar with, such as .side_effect
.
01:52
We’ll set that to a Timeout
.
01:55
So we’ve done patch.object()
on the requests
module, and specifically the .get()
method of that module, and set its .side_effect
to Timeout
.
02:05
And instead of mocked_requests
, let’s call this mocked_get
.
02:11
Previously where we had mocked_requests.get.side_effect
, we actually don’t have to do that anymore because we’re doing that with patch.object()
.
02:19
We’ve set the .side_effect
of .get()
and then with self.assertRaises(Timeout):
we just call get_holidays()
.
02:30 And I’m getting a syntax kind of warning here saying that it’s not used, it’s an Unused variable. We actually don’t need to use it since we’re already, you know, we’re patching it, we’re not using this variable directly.
02:44
So I’m just going to go ahead and change it to an underscore (_
), so that removes the warning there. Let’s save that and try to execute our tests,
02:57
and the test succeeds. Let’s just try to break this just to make sure we’re actually doing something that’s working, so I’m just going to change this to 'getz'
—just, I don’t think there’s an attribute in the requests
module—or an object, rather—called .getdfz
.
03:19
So let’s go ahead and see what happens when we run our tests. Okay, so module 'requests' from
—this path—does not have the attribute 'getdfz'
.
03:29
I just wanted to make sure that what we’re doing is actually working and we are actually patching this particular attribute from requests
. Let’s just run that test again, and it succeeds.
Become a Member to join the conversation.
Glen Jarvis on April 25, 2022
With a context manager, the referencing variable can be omitted if not needed. (That is, there’s no need for the
as _
syntax if the variable is not needed.For example, this is cleaner:
instead of this: