Side Effects: Advanced Test (Part 2)
00:00
So now that we have this kind of helper function, this .log_request()
function within our test class, let’s write a test to test the response with a log statement.
00:13
We’ll make another function called def test_request_with_logging()
.
00:19
Just a side note here, the unittest
module when we run unittest.main()
—it will look for the TestGetHolidays
class and it will run functions that start with test_
.
00:34
We want to make a GET
request to our API, so we’re going to say requests.get.side_effect
, and here instead of passing an exception or something, we’re going to pass this .log_request()
function.
00:51
And rather, this is a self.log_request()
, because it’s inside the class.
00:57
So this is a little magical. First off, remember that requests
is not the actual requests
module—it is a Mock
object.
01:08
We’ve mocked requests
and therefore .get()
is going to be a Mock
object and then .side_effect
is this function.
01:18
So one tricky thing here is that when we set the .side_effect
to a function, it’s going to inherit its arguments and its return value. So in other words, when we say requests.get()
, remember that originally, the arguments of requests.get()
is going to be this URL.
01:45
So since requests
is a Mock
object, we’re saying r
—which is requests.get()
—this argument. So down in our test here, we already have access to that URL endpoint,
02:02
and that is going to be forwarded to this function since we’ve defined it as the .side_effect
. So in a way, it kind of looks like we’re calling this function with this 'localhost/api/holidays'
.
02:21
And I know it’s a little confusing, but it’s just something that you have to know and kind of roll with, is that requests.get()
—which we’ve set up here in our get_holidays()
function—has this argument passed in into it, so to speak.
02:40
So when we make that GET
request inside get_holidays()
, we’re setting the .side_effect
to this function, our .log_request()
function.
02:55
So that means we can do something like assert get_holidays()
—so we call that function—and this should now have a response. So we’re mocking the request and we have the .status_code
at 200
, so that means that get_holidays()
is going to drop into this block and return .json()
, which we have mocked here—we’ve mocked the .return_value
as this dictionary.
03:23
So we should be able to assert that get_holidays()
is going to return a dictionary, and let’s check that the 25th of December is equal to 'Christmas'
.
03:36
Let’s see if this actually works now. I’m going to open up a terminal and we will run our tests. Since we have this unittest.main()
, it should pick up these three tests that start with test_
. In the previous video, we already saw that these should pass, so let’s go ahead and cross our fingers and see if our new test passes.
03:58
So we’ll say python
run my_calendar.py
.
04:04
All right, it passed! It Ran 3 tests
and we also see our log statement here.
Jakub Urbánek on Nov. 25, 2022
For some reason my code is not working. Double checked twice, should be exactly the same, but doesn’t work. Is there any file to download with the whole code?
Bartosz Zaczyński RP Team on Nov. 29, 2022
@Jakub Urbánek Yes, you can click on Supporting Materials | Sample Code from the dropdown just below the video, or grab this link directly: realpython.com/courses/python-mock-object-library/downloads/code-mock/
Become a Member to join the conversation.
artemudovyk on April 13, 2022
It’s was a little bit hard to understand why we should use
side_effect
instead ofreturn_value
.Found this answer that made it clear: