如何模拟被模拟对象返回的对象?
我还不太懂Python中的mock(模拟)用法。
很明显,我不想让我的测试代码去调用实际的requests.post()
方法,所以我想模拟它的行为:
def try_post(self, url, body):
r = requests.post(url, data=body)
msg = str(r.status_code) + " " + r.content + "\n"
if r.status_code >= 300:
sys.stderr.write("Error: POST returned " + msg)
我的问题是:我该如何模拟requests.post()
返回的对象,也就是响应对象呢?
举个例子,我想写一个测试,让r.status_code是200,另一个测试让r.status_code是300,这样我就可以测试条件逻辑。另外,我还需要模拟r.content,让它返回一些字符串。
以下是我写的代码,但没有成功:
from monitor_writer import MonitorWriter
import mock
import unittest
class TestMonitorWriter(unittest.TestCase):
@mock.patch('monitor_writer.requests')
def test_conforming_write(self, mock_requests):
xml_frag = """
<InstantaneousDemand>
</InstantaneousDemand>
"""
mock_requests.status_code.return_value = 200
mock_requests.content.return_value = "OK"
writer = MonitorWriter()
writer.update(xml_frag)
self.assertTrue(mock_requests.post.called, "Failed to call requests.post")
这个测试失败了,报错信息是TypeError: expected a character buffer object
,因为r.status_code和r.content变成了mock.MagicMock对象,而不是字符串,导致try_post()方法试图把它们连接在一起时出错。
1 个回答
2
你想直接模拟 requests.post
这个函数,而不是整个 requests
模块:
class TestMonitorWriter(unittest.TestCase):
@mock.patch('monitor_writer.requests.post')
def test_conforming_write(self, mock_post):
xml_frag = """
<InstantaneousDemand>
</InstantaneousDemand>
"""
response = mock.MagicMock()
response.status_code = 200
respone.content = "OK"
mock_post.return_value = response
writer = MonitorWriter()
writer.update(xml_frag)
self.assertTrue(mock_post.called, "Failed to call requests.post")
一旦我们模拟了你实际调用的那个函数,我们就创建一个模拟的响应对象,然后设置这个模拟响应的 status_code
(状态码)和 content
(内容)为你想要的值,最后把这个模拟的响应赋值给我们模拟的 post
函数的 return_value
(返回值)。