在Python unittest中如何无mock检查函数是否被调用?
如果我有一个像下面这个的类,并且我想测试这个类里的 bar 函数的各种情况,我该怎么做才能不去模拟那些私有函数呢?换句话说,在 Python 的 unittest 库中,我怎样才能做到类似于这个:
def test_bar():
f = Foo()
f.bar(3)
expect(self._is_positive_number).toBeCalled()
foo.py
class Foo():
def bar(self, x):
if type(x) is not int:
print('Please enter a valid integer')
return False
if x > 0:
self._is_positive_number()
elif x == 0:
self._is_zero()
else
self._is_negative()
def _is_positive_number(self):
print('Positive')
return True
def _is_zero(self):
print('Zero')
return True
def _is_negative_number(self):
print('Negative')
return True
2 个回答
2
使用mock
库是一个比较好的选择。
下面是一个完整的示例,展示了三个私有方法。你可以选择更短的名字,如果你喜欢的话,但我觉得用明确的名字更好。需要注意的是,为了安全起见,你应该确认不仅是你想要的方法被调用了,还要确保其他私有方法没有被调用:
from unittest import TestCase
from mock import Mock
class MyTestCase(TestCase):
def setUp(self):
self.instance = Foo()
self.instance._is_positive_number = Mock()
self.instance._is_negative_number = Mock()
self.instance._is_zero = Mock()
def test_positive(self):
self.instance.bar(3)
self.assertTrue(self.instance._is_positive_number.called)
self.assertFalse(self.instance._is_negative_number.called)
self.assertFalse(self.instance._is_zero.called)
def test_negative(self):
self.instance.bar(-3)
self.assertFalse(self.instance._is_positive_number.called)
self.assertTrue(self.instance._is_negative_number.called)
self.assertFalse(self.instance._is_zero.called)
def test_zero(self):
self.instance.bar(0)
self.assertFalse(self.instance._is_positive_number.called)
self.assertFalse(self.instance._is_negative_number.called)
self.assertTrue(self.instance._is_zero.called)
2
据我所知,如果不模拟私有方法,是无法做到这一点的。不过,mock
库(在标准库中从3.3版本开始提供,其他版本需要单独安装)让这个过程变得相对简单:
try:
# Python 3.3 or later
import unittest.mock as mock
except ImportError:
# Make sure you install it first
import mock
class TestFoo(unittest.TestCase):
def setUp(self):
self.f = Foo()
def test_bar(self):
with mock.patch.object(self.f, '_is_positive_number') as is_pos:
self.f.bar(3)
self.assertTrue(is_pos.called)