Python Mock对象与多次调用的方法

我有一个类,我正在testing哪个具有作为依赖另一类(其实例传递给CUT的init方法)。 我想用Python Mock库来嘲笑这个类。

我有什么是这样的:

mockobj = Mock(spec=MyDependencyClass) mockobj.methodfromdepclass.return_value = "the value I want the mock to return" assertTrue(mockobj.methodfromdepclass(42), "the value I want the mock to return") cutobj = ClassUnderTest(mockobj) 

这是好的,但“methodfromdepclass”是一个参数化的方法,因此我想创build一个单一的模拟对象,其中取决于哪些parameter passing给methodfromdepclass它返回不同的值。

我想要这个参数化的行为的原因是我想要创build包含不同的值(其值从mockobj返回什么产生的)的ClassUnderTest的多个实例。

有点什么我在想(这当然是行不通的):

 mockobj = Mock(spec=MyDependencyClass) mockobj.methodfromdepclass.ifcalledwith(42).return_value = "you called me with arg 42" mockobj.methodfromdepclass.ifcalledwith(99).return_value = "you called me with arg 99" assertTrue(mockobj.methodfromdepclass(42), "you called me with arg 42") assertTrue(mockobj.methodfromdepclass(99), "you called me with arg 99") cutinst1 = ClassUnderTest(mockobj, 42) cutinst2 = ClassUnderTest(mockobj, 99) # now cutinst1 & cutinst2 contain different values 

如何实现这个“如果用”的语义types?

尝试side_effect

 def my_side_effect(*args, **kwargs): if args[0] == 42: return "Called with 42" elif args[0] == 43: return "Called with 43" elif kwarg['foo'] == 7: return "Foo is seven" mockobj.mockmethod.side_effect = my_side_effect 

更甜一点:

 mockobj.method.side_effect = lambda x: {123: 100, 234: 10000}[x] 

或多个参数:

 mockobj.method.side_effect = lambda *x: {(123, 234): 100, (234, 345): 10000}[x] 

或者使用默认值:

 mockobj.method.side_effect = lambda x: {123: 100, 234: 10000}.get(x, 20000) 

或两者的组合:

 mockobj.method.side_effect = lambda *x: {(123, 234): 100, (234, 345): 10000}.get(x, 20000) 

高兴地走了。

我在做自己的testing时遇到了这个问题。 如果您不关心如何捕获对您的methodfromdepclass()的调用,但只是需要它返回一些内容,那么以下就足够了:

 def makeFakeMethod(mapping={}): def fakeMethod(inputParam): return mapping[inputParam] if inputParam in mapping else MagicMock() return fakeMethod mapping = {42:"Called with 42", 59:"Called with 59"} mockobj.methodfromdepclass = makeFakeMethod(mapping) 

这是一个参数化的版本:

 def makeFakeMethod(): def fakeMethod(param): return "Called with " + str(param) return fakeMethod