patch() as Decorator
00:00
Let’s open up this tests.py
file and we’ll import the patch()
function. This comes from unittest.mock import patch
.
00:12
We’ll also just import unittest
so we can write some unit tests. And let’s create our first test class, so we’ll say class TestCalendar
, and this inherits from unittest.TestCase
.
00:28
Let’s test our get_holidays()
function. In order to do this, we need to import it into our tests
file. So we’ll say from my_calendar
—that’s the name of our module—we’ll import get_holidays
.
00:48
And let’s do a similar test where we will mock the requests.get()
to have a side effect of a Timeout
. In order to have access to that Timeout
exception, we’ll say from requests.exceptions import Timeout
.
01:04
Then we’ll come into our TestCalendar
class and create a function called .test_get_holidays_timeout()
and this will take self
. And we’ll write a function in here, but first let’s think about what we want to mock.
01:22
So, we want the effect of requests.get()
to be a Timeout
exception. But we haven’t mocked the requests
module. The requests
module is imported in my_calendar
, so we’ve imported requests
because we need it to make a GET
request to our /holidays
API.
01:43
What we want to do is mock this method requests.get()
and have it raise a Timeout
exception as a side effect. Let’s go back into tests.py
and we’ll use the patch()
function as a decorator to patch requests.get()
. So above the test, we’ll decorate it with the @patch()
function.
02:06
And the first argument here is the path to the module that we want to mock, and it’s represented as a string. The path first starts with the module—and that means our local module, my_calendar
—so, 'my_calendar'
and then the module object that we want to patch.
02:26
We want to patch the requests
module—again, which we have imported in my_calendar
. So we’re using @patch()
to patch this particular object—let’s call it an object, just to be clear. This my_calendar
is the module and we’re patching this requests
object in our test.
02:45
And it’s important to know that this is now scoped to this particular test. Anything outside of this test will not have access to this requests
mock.
02:57
And then we also need to pass it as an argument, so this next argument that I’m about to type is the mocked requests
module. I’m just going to call it mocked_requests
, just to be clear.
03:11
Now let’s set the .side_effect
of the mocked_requests.get()
. So we have that module available as mocked_requests
, and we’ll say .get.side_effect
is a Timeout
.
03:26
And now we can write our test that verifies that when we call get_holidays()
, it should raise a Timeout
exception. So with self.assertRaises(Timeout):
we’ll call get_holidays()
. And then to run our test, we’ll create our entry point of if __name__ == '__main__':
we’ll run unittest.main()
.
03:54
I’ll open up my terminal and let’s run python
and give it tests.py
.
04:02
Whoops. We have a little typo. 'my_calendar'
—so where did I type that? There we go. So be sure to make sure your spelling’s correct, but fortunately Python lets us know that it was not.
04:17
And there we go. Our test succeeded. We were able to patch the requests
module—
04:27
the requests
module object—coming from a different module.
04:32
So that means we don’t have to have any mock objects in our codebase—in our core codebase—and we can use patch()
to send them into our tests.
Become a Member to join the conversation.