我有一個被測系統(下面的類Printer
),它使用另一個類(下面的類ContentContainer
)。在一種方法(下面的方法retrieve_and_show_content
)中,這個類被實例化。在這個方法的測試中(下面的方法test_printer_03
),我想實例化一個模擬而不是真實的類。但是,它不能這樣工作。嘲諷在被測方法中實例化的Python類
我讀here,我應該改變名稱與另一個指向的對象。看起來我想要替換的對象的名稱只是ContentContainer
,而我實際替換的對象的名稱是TestMockClass.ContentContainer
。這個觀察是否正確?如果是這樣,我該如何改變這一點?如果我只是在補丁語句中刪除前綴TestMockClass
,我會得到一個TypeError: Need a valid target to patch. You supplied: 'ContentContainer'
。
#TestMockClass.py
import unittest
from mock import Mock, patch
class Printer():
def __init__(self, name, cc):
self.name = name
self.cc = cc
def show_content(self):
text = '{0} says: {1}'.format(self.name, self.cc.content())
return text
def retrieve_and_show_content(self):
cc_tmp = ContentContainer()
text = '{0} says: {1}'.format(self.name, cc_tmp.content())
return text
class ContentContainer():
def __init__(self):
self.method_counter()
def content(self):
return 'Content from ContentContainer'
def method_counter(self):
pass
class Test(unittest.TestCase):
'''No mocking'''
def test_printer_01(self):
cc = ContentContainer()
sut = Printer('P01', cc)
result = sut.show_content()
expected_result = 'P01 says: Content from ContentContainer'
self.assertEqual(result, expected_result,
msg = '\nRetrieved:\n{0} \nExpected:\n{1}'.format(result, expected_result))
result = sut.retrieve_and_show_content()
expected_result = 'P01 says: Content from ContentContainer'
self.assertEqual(result, expected_result,
msg = '\nRetrieved:\n{0} \nExpected:\n{1}'.format(result, expected_result))
'''Create a mock object, which is the input of the method under test'''
def test_printer_02(self):
mock_cc = Mock()
mock_cc.content.return_value = 'Mocked content'
sut = Printer('P02', mock_cc)
result = sut.show_content()
expected_result = 'P02 says: Mocked content'
self.assertEqual(result, expected_result,
msg = '\nRetrieved:\n{0} \nExpected:\n{1}'.format(result, expected_result))
self.assertFalse(mock_cc.method_counter.called, 'Method method_counter shall not be called')
'''Create a mock class, which is instantiated inside the method under test'''
@patch('TestMockClass.ContentContainer')
def test_printer_03(self, mock_cc):
mock_cc.content.return_value = 'Mocked content'
sut = Printer('P03', mock_cc)
result = sut.retrieve_and_show_content()
expected_result = 'P03 says: Mocked content'
self.assertEqual(result, expected_result,
msg = '\nRetrieved:\n{0} \nExpected:\n{1}'.format(result, expected_result))
self.assertFalse(mock_cc.method_counter.called, 'Method method_counter shall not be called')
if __name__ == "__main__":
unittest.main()
當這個單元測試運行時,輸出爲:
AssertionError:
Retrieved:
P03 says: Content from ContentContainer
Expected:
P03 says: Mocked content
冷卻後,從文檔 - '''這意味着您可以訪問「模擬實例」通過看嘲笑class.'的返回值'' – wwii 2014-09-05 16:30:06