How to unit test a decorated method
假设我必须单元测试
1 2 3 4 5 6 7 8 9 10 11 | class SomeClass(object): def wrapper(fun): def _fun(self, *args, **kwargs): self.b = 'Original' fun(self, *args, **kwargs) return _fun @wrapper def methodA(self): pass |
我的测试类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from mock import patch class TestSomeClass(object): def testMethodA(self): def mockDecorator(f): def _f(self, *args, **kwargs): self.b = 'Mocked' f(self, *args, **kwargs) return _f with patch('some_class.SomeClass.wrapper', mockDecorator): from some_class import SomeClass s = SomeClass() s.methodA() assert s.b == 'Mocked', 's.b is equal to %s' % s.b |
如果我运行测试,我点击了断言:
1 2 3 | File"/home/klinden/workinprogress/mockdecorators/test_some_class.py", line 17, in testMethodA assert s.b == 'Mocked', 's.b is equal to %s' % s.b AssertionError: s.b is equal to Original |
如果我在测试中粘贴一个断点,在修补之后,我可以看到
1 2 3 4 | (Pdb) p s.wrapper <bound method SomeClass.mockDecorator of <some_class.SomeClass object at 0x7f9ed1bf60d0>> (Pdb) p s.methodA <bound method SomeClass._fun of <some_class.SomeClass object at 0x7f9ed1bf60d0>> |
知道问题出在这里吗?
仔细研究后,我找到了解决方案。
因为猴子补丁似乎没有效果(我也尝试了一些
其他解决方案),我挖掘了函数内部,这被证明是富有成效的。
Python 3
你很幸运 - 只需使用
Python 2
即使您使用
但是,您只需要意识到包装器方法只执行闭包:因此您将能够在其
在原始示例中,包装函数位于:
结束(哈!)
我沿着这条线创建了一个
1 2 3 | @staticmethod def getWrappedFunction(wrapper): return wrapper.im_func.func_closure[0].cell_contents |
YMMV,特别是如果你做了花哨的东西,并在封闭中包含其他对象。