我想为库对象编写一个模拟而不继承它以便正确测试,但不必存根原始对象的所有未使用的函数。
具体来说,我想为调用库编写一个ContextMock。
class ContextMock:
...
这里的主要问题是我因此调用一个 @task 函数,然后该函数调用我想要测试的代码。然而 @task 装饰器检查上下文对象是否是 Context 的实例,如下所示:
def __call__(self, *args, **kwargs):
# Guard against calling tasks with no context.
if not isinstance(args[0], Context):
err = "Task expected a Context as its first arg, got {} instead!"
# TODO: raise a custom subclass _of_ TypeError instead
raise TypeError(err.format(type(args[0])))
因此我的问题是,我能否以某种方式更改 ContextMock 的 isinstance 函数,或者使其看起来像 Context 的实例而不继承其属性? 或者是否可以以某种方式模拟 isinstance 函数? instancecheck 的默认实现是如何工作的?是否有一个可以被覆盖的基类属性?
我已经尝试提供一个带有自定义 instancecheck 函数的自定义元类,这当然不起作用,因为调用了 Context 的 instancecheck,对吧?
另请注意,我很清楚任何黑客解决方案都不应该属于生产代码,并且仅用于测试。
编辑: 添加我想要存档的通用示例:
class Context:
pass
class ContextMock:
pass
mock = ContextMock
... do magic with mock
assert isinstance(mock, Context)
您只需提供
spec_set
或 spec
至 unittest.mock.Mock
即可实现此目的。示例
>>> class Context:
pass
>>> mock = Mock(spec_set=Context)
>>> isinstance(mock, Context)
True
如果您需要使
mock
返回某些方法的某些特定值,您可以使用 mock.somemethod.return_value = someval