如何在Python中对猴子补丁进行单元测试

时间:2012-10-10 14:55:50

标签: python unit-testing monkeypatching

我有一个行为方式,就像这样

def my_patch_method(self):
    pass

def patch_my_lib():
    from mylib import MyClass
    MyClass.target_method = my_patch_method
    return MyClass()

此测试失败:

self.assertEqual(my_patch_method, patch_my_lib().target_method)

这个有效:

self.assertEqual(my_patch_method.__name__, patch_my_lib().target_method.__name__)

由于补丁方法的名称不同,这仍然可以证明patch_my_lib()正在做它所付出的代价,但为什么第一个工作不像我期望的那样?并且,有没有办法“修复”它?

4 个答案:

答案 0 :(得分:3)

你的第一次测试失败的原因是,一旦你将函数修补到你的类中,它就不再是同一个对象了。

>>> def foo(self): pass
... 
>>> class Foo: pass
... 
>>> Foo.bar = foo
>>> type(Foo.bar)
<type 'instancemethod'>
>>> type(foo)
<type 'function'>
>>> 
>>> Foo.bar is foo
False
>>> Foo.bar == foo
False

实际上,原始功能和新方法有不同的类型。相反,让你的第一次测试检查这个条件:

>>> Foo.bar.im_func is foo
True

所以也许这样:self.assertIs(my_patch_method, patch_my_lib().target_method.im_func)

答案 1 :(得分:2)

尝试:

self.assertEqual(my_patch_method, patch_my_lib().target_method.im_func)

答案 2 :(得分:1)

您正在从patch_my_lib返回一个实例,因此将该函数与绑定方法进行比较

这样的事情应该通过

self.assertEqual(my_patch_method, patch_my_lib().target_method.im_func)

但是,检查您正在修补的行为是否有效

可能更好

答案 3 :(得分:0)

MyClass.target_method = my_patch_method将您的函数设置为MyClass的类函数,但是您返回该类的实例return MyClass()