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

如何在Python中对monkey补丁进行单元测试,python,unit-testing,monkeypatching,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) 鉴于这一点有效: s

我有一个实用方法,其行为如下

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方法没有相同的名称,这仍然是可以接受的证据,证明
patch\u my_lib()
正在做它应该做的事情,但是为什么第一个方法不能像我期望的那样工作呢?还有,有没有办法“修复”它?

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

这样的事情应该过去

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

但是最好检查您正在修补的行为是否正常工作

MyClass.target\u method=my\u patch\u method
将您的函数设置为
MyClass
的类函数,但您将使用
return MyClass()
返回该类的实例

试试看:

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

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

>>> 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

所以可能是这样:
self.assertIs(my_patch\u method,patch\u my_lib().target\u method.im\u func)

这是因为
my_patch\u method
是一个未绑定的函数,而
patch\u my_lib().target\u method
是一个绑定的方法。非常感谢所有这些细节。
>>> Foo.bar.im_func is foo
True