71

別のクラス (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」はパラメーター化されたメソッドであるため、methodfromdepclass に渡される引数に応じて異なる値を返す単一のモック オブジェクトを作成したいと考えています。

このパラメーター化された動作が必要な理由は、異なる値 (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

この「ifcallwith」のようなセマンティクスを実現するにはどうすればよいですか?

4

4 に答える 4

97

試す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 kwargs['foo'] == 7:
        return "Foo is seven"

mockobj.mockmethod.side_effect = my_side_effect
于 2011-10-05T18:15:04.587 に答える
60

少し甘い:

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)

そして、陽気に私たちは行きます。

于 2012-11-29T23:04:56.597 に答える
11

私は自分のテストを行っていたときにこれに遭遇しました。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
于 2012-06-03T07:58:02.727 に答える