python - 如何使用 pytest-mock 有条件地模拟函数
问题描述
我有一门课foo.py
,我想测试:
import requests
class Foo:
def fooMethod(self, url):
response = requests.get(url)
return response
我想替换requests
调用来模拟响应。
这是我的测试文件test_foo.py
:
from foo import Foo
def mocked_requests_get(*args, **kwargs):
class MockResponse:
def __init__(self, text, code):
self.text = text
self.code = code
if args[0] == "http://localhost":
return MockResponse("Test response", 200)
return MockResponse(None, 404)
class TestFoo:
def test_foo(self, mocker):
a = Foo()
mocker.patch ('foo.requests.get', mocked_requests_get)
spy = mocker.spy (a, 'test_foo.mocked_requests_get')
response = a.fooMethod("http://localhost")
assert response.text == "Test response"
assert spy.call_count == 1
我想检查该mocked_requests_get
函数是否只被调用一次。
解释器在该行给出错误spy = mocker.spy ...
:
'Foo' object has no attribute 'test_foo.mocked_requests_get'
这是可以理解的 - 但我无法找到一种方法来获取引用该函数的对象实例。有人可以帮忙吗?
解决方案
你的方法有点太复杂了——你可以只使用一个标准的模拟,而不需要实现你自己的模拟类。像这样的东西应该工作:
class TestFoo:
def test_foo(self, mocker):
a = Foo()
get_mock = mocker.patch('requests.get')
get_mock.return_value.text = "Test response"
response = a.fooMethod()
assert response.text == "Test response"
assert get_mock.call_count == 1
另请注意,您必须修补requests.get
而不是foo.requests.get
,因为您直接导入requests
(请参阅修补位置)。
更新:
如果您需要响应依赖于 url,如更新后的问题所示,您可以使用side_effect
,它可以采用函数或类对象(除非return_value
,它需要评估值):
class MockedResponse:
def __init__(self, url):
self.url = url
@property
def text(self):
responses = {"url1": "response1",
"url2": "response2",
"url3": "response3"}
if self.url in responses:
return responses[self.url]
return "default"
class TestFoo:
def test_foo(self, mocker):
a = Foo()
get_mock = mocker.patch('requests.get')
get_mock.side_effect = MockedResponse
response = a.fooMethod("url2")
assert response.text == "response2"
assert get_mock.call_count == 1
推荐阅读
- python-3.x - 如何使用 python 和 boto3 将 xlsx 导入 dynamodb
- python - 对象检测 API 未找到 CUDA 库错误
- java - 将数据从 ReadableByteChannel 传输到文件
- batch-file - 使用 Windows Batch 从输出中检索信息
- javascript - 使用 javascript 向 Restful Web 服务发布请求
- html - 悬停下拉菜单外观
- mysql - MySQL Select 语句不返回任何结果
- c - 多个 #ifndef 语句 - 应用哪一个
- matlab - 如何在下面的代码中避免翻转?
- ruby - Ruby Watir 参考 Chrome 打印预览