问题描述
我尝试使用 mock 在 python 中编写一些单元测试.
I try to use mock to write some unit-tests in python.
例如我有以下课程:
class TCPHandler(socketserver.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip()
我只想测试 handle 方法.无需对 socketserver.BaseRequestHandler 做任何假设.例如,我想断言 handle 使用参数 1024 调用 recv.可以用模拟做这样的事情吗?IE.用模拟替换基类 socketserver.BaseRequestHandler?还是我偏离了这个想法?
And I only want to test the handle method. Without having to assume anything about socketserver.BaseRequestHandler. I for example want to assert that handle calls recv with the argument 1024. Is it possible to do such thing with mock? I.e. replacing the base class socketserver.BaseRequestHandler with a mock? Or am I off track with that idea?
在 ecatmur 的回答下(谢谢!)我首先尝试了以下方法:
With the answer of ecatmur (thank you!) I first tried the following:
patcher = patch.object(TCPHandler, '__bases__', (Mock,)) with patcher: patcher.is_local = True handler = TCPHandler() handler.handle()
但是现在 handle 不再被调用并且 dir(handler) 给出:
But now handle is not called anylonger and dir(handler) gives:
['assert_any_call', 'assert_called_once_with', 'assert_called_with', 'assert_has_calls', 'attach_mock', 'call_args', 'call_args_list', 'call_count', 'called', 'configure_mock', 'method_calls', 'mock_add_spec', 'mock_calls', 'reset_mock', 'return_value', 'side_effect']
type(handler) 给出<class 'mock.TCPHandler'>
我解释说,修补基类也会将我的派生类变成一个模拟类.
Which I interpret that patching the base class also turns my derived class into a mock.
我现在尝试了另一个想法:
I now gave another idea a try:
mock = MagicMock() TCPHandler.handle(mock) #assertions
但是模拟似乎没有被调用.
However the mock seems not to be called.
推荐答案
您可以通过修补派生类的 __bases__ 来做到这一点:
You can do this by patching the derived class's __bases__:
def test_derived(): patcher = mock.patch.object(Derived, '__bases__', (mock.Mock,)) with patcher: patcher.is_local = True d = Derived() print d.foo()
is_local hack 是阻止 mock.patch 在反转补丁时尝试调用 delattr 所必需的.
The is_local hack is necessary to stop mock.patch from trying to call delattr when reversing the patch.