我有一个昂贵的__init__
函数的类。我不想从测试中调用这个函数。避免执行模拟类的__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__
函数,但我的断言失败,因为结果最终是一个模拟实例,而不是我的价值。
我也试图在setUp
功能配置patch
例如,使用start
和stop
功能the docs suggest。
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__
类,该类是由我的测试代码实例化的?理想情况下,我希望有一个解决方案适用于TestCase类中的许多单元测试(例如,不需要每次测试都需要patch
)。
我正在使用Python版本2.7.6
。
如何让'ClassWithComplexInit'可用于您的测试脚本? '从mypackage导入ClassWithComplexInit'或其他东西? – chepner 2014-11-05 21:17:48
@chepner我的测试脚本甚至没有导入'ClassWithComplexInit'。我从我的真实代码切换了一堆代码在SO上发布,并搞砸了包引用,我意识到引用是错误的。你在回答中解决了这个问题,谢谢! – 2014-11-05 22:14:34