使用模拟更改函数调用的第二个结果
Changing the second result of a function call with mock
我有一个看起来像这样的循环:
for i in range(len(some_list)):
response = requests.post(some_url, some_params)
if response.status_code != HTTPOk:
# do something
我想做的是在循环的第二次迭代中更改 requests.post 的响应。在我的测试中,我知道我可以做类似的事情:
mock_response = mock.Mock()
mock_response.status_code = 404
with mock.patch(mymodule.requests.post, return_value=mock_response):
mymodule.some_function()
但这似乎只适用于一个 status_code。我查看了 side_effect,看起来我可以像这样遍历循环:
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()
但是,它似乎并没有真正获得 "right" 状态代码。更改 side_effect 或 return_value 中的行为以正确获得我想要的行为的最佳方式是什么?我认为 side_effect 是我想要的,但我不确定模拟响应的最佳方法是什么。
其实很简单:
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()
更简单、更干净的方法是
with mock.patch("mymodule.requests.post",
side_effect=[Mock(status_code=400), Mock(status_code=200)]) as mock_post:
mymodule.some_function()
patch
通过 MagicMock(side_effect=mock_responses)
创建 mock_post
对象并替换 mymodule.requests.post
引用。您还可以使用 mock_post
通过以下方式检查 post()
调用:
mock_post.assert_has_calls([mock.call(first_url, first_params), mock.call(second_url, second_params)])
您可以通过构建和配置 mock_post
来完成相同的工作,然后将其作为 new
参数(第二个 patch
参数)传递,但是通过这种方式您有 2 个缺点
- 要编写更多代码
- 无法在
patch
中使用 autospec=True
选项
Autospeccing 是 mock
框架的一个非常强大的功能,可以防止在测试和代码中出现很多愚蠢的错误。
我有一个看起来像这样的循环:
for i in range(len(some_list)):
response = requests.post(some_url, some_params)
if response.status_code != HTTPOk:
# do something
我想做的是在循环的第二次迭代中更改 requests.post 的响应。在我的测试中,我知道我可以做类似的事情:
mock_response = mock.Mock()
mock_response.status_code = 404
with mock.patch(mymodule.requests.post, return_value=mock_response):
mymodule.some_function()
但这似乎只适用于一个 status_code。我查看了 side_effect,看起来我可以像这样遍历循环:
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()
但是,它似乎并没有真正获得 "right" 状态代码。更改 side_effect 或 return_value 中的行为以正确获得我想要的行为的最佳方式是什么?我认为 side_effect 是我想要的,但我不确定模拟响应的最佳方法是什么。
其实很简单:
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()
更简单、更干净的方法是
with mock.patch("mymodule.requests.post",
side_effect=[Mock(status_code=400), Mock(status_code=200)]) as mock_post:
mymodule.some_function()
patch
通过 MagicMock(side_effect=mock_responses)
创建 mock_post
对象并替换 mymodule.requests.post
引用。您还可以使用 mock_post
通过以下方式检查 post()
调用:
mock_post.assert_has_calls([mock.call(first_url, first_params), mock.call(second_url, second_params)])
您可以通过构建和配置 mock_post
来完成相同的工作,然后将其作为 new
参数(第二个 patch
参数)传递,但是通过这种方式您有 2 个缺点
- 要编写更多代码
- 无法在
patch
中使用
autospec=True
选项
Autospeccing 是 mock
框架的一个非常强大的功能,可以防止在测试和代码中出现很多愚蠢的错误。