我有一个昂贵的__init__
函数的类。我不希望从测试中调用此函数。
出于本示例的目的,我创建了一个在__init__
中引发异常的类:
class ClassWithComplexInit(object):
def __init__(self):
raise Exception("COMPLEX!")
def get_value(self):
return 'My value'
我有第二个类构造ClassWithComplexInit
的实例并使用它的函数。
class SystemUnderTest(object):
def my_func(self):
foo = ClassWithComplexInit()
return foo.get_value()
我正在尝试围绕SystemUnderTest#my_func()
编写一些单元测试。我遇到的问题是无论我如何尝试模拟ClassWithComplexInit
,__init__
函数总是被执行并引发异常。
class TestCaseWithoutSetUp(unittest.TestCase):
@mock.patch('mypackage.ClassWithComplexInit.get_value', return_value='test value')
def test_with_patched_function(self, mockFunction):
sut = SystemUnderTest()
result = sut.my_func() # fails, executes ClassWithComplexInit.__init__()
self.assertEqual('test value', result)
@mock.patch('mypackage.ClassWithComplexInit')
def test_with_patched_class(self, mockClass):
mockClass.get_value.return_value = 'test value'
sut = SystemUnderTest()
result = sut.my_func() # seems to not execute ClassWithComplexInit.__init__()
self.assertEqual('test value', result) # still fails
# AssertionError: 'test value' != <MagicMock name='ClassWithComplexInit().get_value()' id='4436402576'>
上面的第二种方法是我从this similar Q&A获得的方法,但它也没有用。它似乎似乎不运行__init__
函数,但我的断言失败,因为结果最终是一个模拟实例,而不是我的值。
我还尝试使用patch
和setUp
函数start
在stop
函数中配置class TestCaseWithSetUp(unittest.TestCase):
def setUp(self):
self.mockClass = mock.MagicMock()
self.mockClass.get_value.return_value = 'test value'
patcher = mock.patch('mypackage.ClassWithComplexInit', self.mockClass)
patcher.start()
self.addCleanup(patcher.stop)
def test_my_func(self):
sut = SystemUnderTest()
result = sut.my_func() # seems to not execute ClassWithComplexInit.__init__()
self.assertEqual('test value', result) # still fails
# AssertionError: 'test value' != <MagicMock name='mock().get_value()' id='4554658128'>
个实例。
__init__
这似乎也避免了我的get_value.return_value
功能,但我为get_value()
设置的值没有得到尊重,MagicMock
仍在返回__init__
个实例。
如何模拟具有复杂patch
的类,该类由我的测试代码实例化?理想情况下,我想要一个适用于TestCase类中许多单元测试的解决方案(例如,不需要每次测试2.7.6
)。
我使用的是Python版{{1}}。
答案 0 :(得分:2)
首先,您需要使用与修补相同的名称来创建foo
,即
class SystemUnderTest(object):
def my_func(self):
foo = mypackage.ClassWithComplexInit()
return foo.get_value()
其次,您需要配置正确的模拟对象。您正在配置未绑定方法ClassWithComplexInit.get_value
,但您需要配置ClassWithComplexInit.return_value.get_value
,这是Mock
对象,实际上将使用foo.get_value()
进行调用。
@mock.patch('mypackage.ClassWithComplexInit')
def test_with_patched_class(self, mockClass):
mockClass.return_value.get_value.return_value = 'test value'
sut = SystemUnderTest()
result = sut.my_func() # seems to not execute ClassWithComplexInit.__init__()
self.assertEqual('test value', result) # still fails
答案 1 :(得分:-1)
为什么不将它子化为测试并覆盖init?
class testClassWithComplexInit(ClassWithComplexInit):
def __init__(self):
pass
ClassWithComplexInit = testClassWithComplexInit
现在,ClassWithComplexInit().get_value()
返回'My value'
而非提出异常。