带参数或调用的模拟python实例方法

2024-05-17 02:36:32 发布

您现在位置:Python中文网/ 问答频道 /正文

给定具有依赖于实例变量的实例方法foo的任何类,例如


class A:
    def __init__(self, x: int):
        self.x = x

    def foo(self, y: int):
        return self.x * y


def test_foo(mocker):
    a = A(1)
    y = -10
    assert a.foo(y) < 0
    mocker.patch.object(a, "foo", return_value=a.x * abs(y))
    assert a.foo(y) > 0

问题是如何仅为感兴趣的测试值模拟A(1).foo(y),例如y < 0,否则返回对A(1).foo(y)的原始调用?在上面的这个例子中,y值是已知的,但是对于这个问题,请假设它是未知的(比如说,在第三方代码中很深),并且必须从对foo()的调用中检查它。python模拟似乎适用于对A(1).foo(y)的所有调用,而没有任何选项,通过检查方法调用参数,仅对y的特定值应用模拟

例如,使用pytest mock,上面的测试可以工作,但它没有检查方法调用、检查方法调用的参数以及仅在参数与某些感兴趣的值匹配时注入模拟,或者调用原始方法的选项

解决方案是创建A的子类,该子类可以检查args并返回模拟值或调用super,然后使用模拟将该子类替换为A?例如,基于上述示例代码:


class B(A):

    def foo(self, y: int):
        if y < 0:
            return self.x * abs(y)
        else:
            super().foo(y)


def test_b_foo(mocker):
    a = A(1)
    y = -10
    assert a.foo(y) < 0
    mocker.patch.object(A, "foo", side_effect=B(a.x).foo)
    assert a.foo(y) > 0

这工作正常,但它假设A已经初始化,并且它使用实例a来初始化B。模拟如何将对A(i)的调用替换为对B(i)的调用,以便测试实际调用B(i).foo(y)?当针对某个特定yA(i).foo(y)的特定参数的mock应应用于A.foo方法时,会发生什么情况,无论该方法是如何初始化的或何时初始化的?我正在寻找类似ruby mock的东西,它仅在使用某些特定参数调用修补对象(方法)时才应用模拟返回值。似乎某种间谍可以在检测到带有特定参数的方法调用时动态注入返回值(以使原始方法短路),但在其他情况下调用原始方法。我想应该是这样的:

m = mock.patch.object(A, "foo")
m.called_with(y < 0).return_value = mock_specific_to_args
# otherwise m.foo(10) calls the original method

Tags: 实例方法self参数returnobjectfoodef
1条回答
网友
1楼 · 发布于 2024-05-17 02:36:32

检查y的值以决定是否模拟A.foo

def test_foo(mocker):
    a = A(1)
    y = -10
    assert a.foo(y) < 0
    if y < 0:
        mocker.patch.object(a, "foo", return_value=a.x * abs(y))
    assert a.foo(y) > 0

相关问题 更多 >