当在另一个方法中调用目标方法时,Python 模拟不会断言调用

问题描述 投票:0回答:1

我无法在某些方法在内部调用其他方法的类中执行一些基本的

assert_called()

示例代码:

from unittest.mock import Mock


class Foo:
    def print1(self) -> None:
        print("print1 called")  # I see this print message
        self.print2()
        
    def print2(self) -> None:
        print("print2 called")  # I see this print message

foo = Foo()
foo_mock = Mock(wraps=foo)
foo_mock.print1()
foo_mock.print1.assert_called()  # OK
foo_mock.print2.assert_called()  # NOT OK

问题似乎在于

print1(self)
self
的实例属于
Foo
类型,而不是
Mock
类型。这就是为什么没有任何关于模拟调用的寄存器
print2

这是预期的行为吗?通常,

self
绑定到调用者对象。这意味着应该传递
Mock
类型的实例。我猜问题是因为实例已经创建,因此所有方法都绑定到非模拟实例。我希望这会被
Mock
__init__
修改。

这个问题有什么解决办法吗?我是不是做错了什么?

编辑:

我发现这个问题可以通过这样做来解决:

import types
from unittest.mock import Mock


class Foo:
    def print1(self) -> None:
        print("print1 called", type(self))
        self.print2()
        
    def print2(self) -> None:
        print("print2 called")

foo = Foo()
foo_mock = Mock(wraps=foo)

setattr(foo_mock, "print1", types.MethodType(Mock(wraps=Foo.print1), foo_mock))  # FIX
setattr(foo_mock, "print2", types.MethodType(Mock(wraps=Foo.print2), foo_mock))  # FIX

foo_mock.print1()
foo_mock.print1.assert_called()
foo_mock.print2.assert_called()
python mocking python-unittest python-mock python-unittest.mock
1个回答
0
投票

问题似乎在于

print1(self)
self
的实例属于
Foo
类型,而不是
Mock
类型。这就是为什么没有任何关于模拟调用的寄存器
print2
。这是预期的行为吗?

是的。

wraps:模拟对象要包装的项目。 如果wraps不是None,那么调用Mock会将调用传递给包装对象(返回真实结果)。模拟上的属性访问将返回一个模拟对象,该对象包装了包装对象的相应属性(因此尝试访问不存在的属性将引发

AttributeError
)。

您正在包装

foo
,它是类
Foo
的真实实例。任何属性访问都是真实的。使用
wraps
可能会导致真正的 I/O 执行,而您的测试可能没有预料到。仅当您的测试依赖于实际输出时才使用
wraps

© www.soinside.com 2019 - 2024. All rights reserved.