如何模拟被模拟对象返回的对象?

时间:2014-09-13 01:00:55

标签: python unit-testing mocking

我不太熟悉Python嘲笑。

显然,我不希望我的测试代码在以下方法中调用实际方法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 个答案:

答案 0 :(得分: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_codecontent,最后将模拟的响应分配给我们的模拟return_value函数的post