2014-09-13 167 views
0

我不太喜歡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()方法試圖鏈接它們。

回答

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上對所需值的模擬響應,最後將模擬的響應分配給我們嘲弄的post函數的return_value

+0

現在我明白了,這很有道理。它的工作原理。謝謝你讓我直截了當。 (FWIW,在我讀過的幾個教程和快速入門中我找不到這個)。 – 2014-09-13 02:03:56