python模拟库-在单元测试时修补类 [英] python mock library - patching classes while unit testing

查看:111
本文介绍了python模拟库-在单元测试时修补类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法理解模拟补丁的工作原理,以及它是否能够解决我的问题.

I cannot understand how mock patch works and if does it able to solve my problem.

我有3个文件:与外部接口(a.py),业务逻辑(b.py)和测试(test.py)的通信.我想在运行测试时修补业务逻辑使用的外部接口.

I have 3 files: communication with external interface (a.py), business logic (b.py) and tests (test.py). I want to patch external interface that is used by business logic while running tests.

a.py:

class SomeProductionClassINeedPatch(object):
    name = 'Production Class (communication with some external service)'
    def do_something(self):
        print '<some feature with external service>'

b.py:

import mock
from src.tmp.mocks.a import SomeProductionClassINeedPatch

class WorkingClass(object):
    def some_method_that_uses_external_class(self, *args):
        external = self._external
        external.do_something()

    @property
    def _external(self):
        if not hasattr(self, '_ext_obj' or not self._ext_obj):
            self._ext_obj = SomeProductionClassINeedPatch()
            print isinstance(self._ext_obj, mock.MagicMock) # False
        return self._ext_obj

b = WorkingClass()
b.some_method_that_uses_external_class()

test.py:

import mock
from src.tmp.mocks.b import WorkingClass    # class I want to test

@mock.patch('src.tmp.mocks.a.SomeProductionClassINeedPatch')
def test_some_method_of_working_class(external_mock=None, *args):
    o = WorkingClass()
    o.some_method_that_uses_external_class()        # external interface wasn't patched: <some feature with external service> - but I need mock here!
    print '<test> - '+str(isinstance(o._external, mock.MagicMock))  # False

test_some_method_of_working_class()

我希望在 test.py 中调用o.some_method_that_uses_external_class()不会实际使用外部接口,而是使用模拟对象.但是似乎仍然使用实际的对象.

I expect that calling o.some_method_that_uses_external_class() in test.py will not actually use external interface, but mock object. But seems still actual object is used.

此外,当我在test.py或b.py中检查外部接口对象的实例时-我无法使它们通过 isinstance(object,MagicMock)检查,它始终返回false.即使我尝试在 b.py 中应用相同的补丁程序(作为类装饰器).我在做什么错了?

Also when I check instance of external interface object either in test.py or in b.py - I cannot make them to pass isinstance(object, MagicMock) check, it always return false. Even if I try to apply the same patch in b.py (as class decorator). What am I doing wrong?

如果重要的话,我使用python 2.7和Michael Foord的模拟库1.0.

I use python 2.7 and mock library 1.0 by Michael Foord if that matters.

推荐答案

修补程序通过(临时)将一个名称指向的对象更改为另一个来工作.可以有许多名称指向任何单个对象,因此,要使修补程序正常工作,必须确保对被测系统使用的名称进行修补.

patch works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.

在您的示例中,使用要修补的对象的代码在模块b中.调用patch时,该类已经导入到模块b中,因此修补ab无效.您需要改为在b中放置对象的路径:

In your example, the code using the object you want patched is in module b. When you call patch, the class has already been imported in module b, so patching a will have no effect on b. You need instead to path the object in b:

@mock.patch('src.tmp.mocks.b.SomeProductionClassINeedPatch')

这将为您提供预期的结果,b的第一个调用未打补丁,而test的第二个调用使用了模拟对象:

This will give you the expected result, the first call from b is unpatched, while the second call from test used the mock object:

# python test.py
False
<some feature with external service>
True
<test> - True

这篇关于python模拟库-在单元测试时修补类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆