使用python mock统计方法调用次数
我刚开始使用Python的模拟框架。我想要做的就是统计一个方法被调用的次数,但又不想去掉调用这个方法的实际效果。
比如,在这个简单的计数器例子中,我希望既能增加计数器的值,又能记录这个方法被调用了:
import unittest
import mock
class Counter(object):
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
class CounterTest(unittest.TestCase):
def test_increment(self):
c = Counter()
c.increment()
self.assertEquals(1, c.count)
def test_call_count(self):
with mock.patch.object(Counter, 'increment') as fake_increment:
c = Counter()
self.assertEquals(0, fake_increment.call_count)
c.increment()
self.assertEquals(1, fake_increment.call_count)
# increment() didn't actually get called.
self.assertEquals(1, c.count) # Fails.
if __name__ == '__main__':
unittest.main()
有没有办法让mock
在记录了调用之后,继续调用被模拟的方法,或者只是表示我想保留这个模拟函数的效果呢?
2 个回答
3
我对模拟(mock)这块不是特别有经验,但我用一个函数包装器实现了这个功能,而不是使用默认的 MagicMock
:
class FuncWrapper(object):
def __init__(self, func):
self.call_count = 0
self.func = func
def __call__(self, *args, **kwargs):
self.call_count += 1
return self.func(*args, **kwargs)
class CounterTest(unittest.TestCase):
def test_call_count(self):
c = Counter()
new_call = FuncWrapper(c.increment)
with mock.patch.object(c, 'increment', new=new_call) as fake_increment:
print fake_increment
self.assertEquals(0, fake_increment.call_count)
c.increment()
self.assertEquals(1, fake_increment.call_count)
self.assertEquals(1, c.count) # Fails.
当然,这个 FuncWrapper
非常简单。它只是用来计算调用次数,然后把控制权交回给原来的函数。如果你需要同时测试其他内容,就得在 FuncWrapper
类里添加一些东西。我还只是对一个类的实例进行了修改,而不是整个类。这样做的主要原因是我需要在 FuncWrapper
里用到一个实例方法。
1其实我刚开始学习这方面的知识——算你们被警告了 ;-).
12
只需使用 wraps:
c = Counter()
with mock.patch.object(Counter, 'increment', wraps=c.increment) as fake_increment:
如果你稍后再初始化 c
,可能会出现一些绑定问题,因为传给 wraps
的函数不会知道 self
是什么。