gpt4 book ai didi

python - 模拟在被测方法中实例化的 Python 类

转载 作者:行者123 更新时间:2023-11-28 19:55:39 28 4
gpt4 key购买 nike

我有一个正在测试的系统(下面的 Class Printer),它使用另一个类(下面的 Class ContentContainer)。在一个方法中(下面的方法 retrieve_and_show_content),这个类被实例化。在对该方法(下面的方法 test_printer_03)的测试中,我想实例化一个 mock 而不是真正的类。然而,它不是这样工作的。

我读了here我应该将 name 指向的对象更改为另一个对象。似乎我要替换的对象的名称只是ContentContainer,而我实际要替换的对象的名称是TestMockClass.ContentContainer。这个观察是否正确?如果是这样,我该如何更改?如果我简单地删除补丁语句中的前缀 TestMockClass,我会得到一个 TypeError: Need a valid target to patch。您提供了:“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

最佳答案

两件事:

  1. 因为 ContentContainer 现在与测试在同一个文件中,您实际上需要修补 __main__.ContentContainer:

    @patch('__main__.ContentContainer')
  2. 因为 ContentContainer 是一个类,而您在该类的实例上调用 content,您实际上希望模拟 content 在那个实例上,而不是在类里面。因此你需要做:mock_cc.return_value.content.return_value = 'Mocked content'不是类(class))。这是因为调用一个类会创建一个实例。所以,实例就是类调用的返回值。

因此测试应该如下所示:

@patch('__main__.ContentContainer')
def test_printer_03(self, mock_cc):
mock_cc.return_value.content.return_value = 'Mocked content'
...

关于python - 模拟在被测方法中实例化的 Python 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25689412/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com