Modifying the second result of a function call with mock

I have a loop that looks like this:

for i in range(len(some_list)):
    response = requests.post(some_url, some_params)
    if response.status_code != HTTPOk:
       # do something

      

What I would like to do is change the response of request.post in the second iteration of the loop. From my test, I know I can do something like:

mock_response = mock.Mock()
mock_response.status_code = 404
with mock.patch(mymodule.requests.post, return_value=mock_response):
   mymodule.some_function()

      

But this only works for one status_code. I looked at side_effect and it looks like I can iterate over the loop this way:

mock_response.side_effect = [
    mock.Mock(status_code=400), mock.Mock(status_code=200)
]
with mock.patch(mymodule.requests.post, return_value=mock_response):
   mymodule.some_function()

      

However, it looks like it is not actually getting the "correct" status code. What's the best way to change the behavior in side_effect or return_value in order to get the behavior I want correctly? I think side_effect is what I want, but I'm not sure if the best way is to mock the answers.

+3


source to share


2 answers


An easier and more straightforward way to do it

with mock.patch("mymodule.requests.post", 
                side_effect=[Mock(status_code=400), Mock(status_code=200)]) as mock_post:
   mymodule.some_function()

      

patch

create mock_post

an object MagicMock(side_effect=mock_responses)

and replace the link mymodule.requests.post

. You can also use mock_post

to test calls post()

like this:

mock_post.assert_has_calls([mock.call(first_url, first_params), mock.call(second_url, second_params)])

      



You can do the same job with build and configure mock_post

before and then pass it as a parameter new

(second argument patch

), but this way you have 2 disadvantages

  • More code to write
  • Can't use options autospec=True

    inpatch

Autospeccing is a very powerful framework feature mock

that prevents many silly bugs in both test and code.

+2


source


It actually turns out that it was simple:



mock_response.side_effect = [
    mock.Mock(status_code=400), mock.Mock(status_code=200)
]
with mock.patch(mymodule.requests.post, mock_response):
   mymodule.some_function()

      

0


source







All Articles