模拟python单元测试中的类和类方法
我正在使用python的unittest.mock在Django应用程序中执行一些测试。我想检查一个类是否被调用,并且它的实例上的方法也被调用。模拟python单元测试中的类和类方法
例如,给定这个简化的示例代码:
# In project/app.py
def do_something():
obj = MyClass(name='bob')
return obj.my_method(num=10)
而这个测试来检查发生的事情:
# In tests/test_stuff.py
@patch('project.app.MyClass')
def test_it(self, my_class):
do_something()
my_class.assert_called_once_with(name='bob')
my_class.my_method.assert_called_once_with(num=10)
试验成功说my_class
被调用,但是他说,my_class.my_method
不调用。我知道我错过了一些东西 - 嘲笑模拟课堂上的一种方法? - 但我不确定什么或如何使它工作。
你的第二个模拟断言需要测试你是在实例调用my_method
,而不是类本身。
调用模拟对象这样,
my_class().my_method.assert_called_once_with(num=10)
^^
如果my_method
是一个类的方法这一行
my_class.my_method.assert_called_once_with(num=10)
会工作。
是这样吗?
否则,如果my_method
仅仅是一个正常的实例方法,那么你就需要重构功能do_something
来获得实例变量obj
例如握住
def do_something():
obj = MyClass(name='bob')
return obj, obj.my_method(num=10)
# In tests/test_stuff.py
@patch('project.app.MyClass')
def test_it(self, my_class):
obj, _ = do_something()
my_class.assert_called_once_with(name='bob')
obj.my_method.assert_called_once_with(num=10)
谢谢安东尼。在某种程度上,这与Jared的回答有何不同? (我不是说它不是,我只是不明白就知道!) –
小重构建议为你的单元测试,以帮助其他的实例方法你可能在你的测试遇到。而不是在每种方法中嘲笑你的课程,你可以在setUp
方法中设置这一切。这样,当班级嘲笑并从该班级创建模拟对象时,您现在可以根据需要多次使用该对象,测试班级中的所有方法。
为了说明这一点,我将下面的例子放在一起。评论在线:
class MyTest(unittest.TestCase):
def setUp(self):
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
# create your mock object
self.mock_stuff_obj = Mock()
# When your real class is called, return value will be the mock_obj
self.my_class.return_value = self.mock_stuff_obj
def test_it(self):
do_something()
# assert your stuff here
self.my_class.assert_called_once_with(name='bob')
self.mock_stuff_obj.my_method.assert_called_once_with(num=10)
# stop the patcher in the tearDown
def tearDown(self):
self.patcher.stop()
提供关于这是如何放在一起时,setUp
方法,我们将提供功能能够跨作为文档here解释多种方法应用补丁里面的一些见解。
的修补是在这两条线进行:
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
最后,在这里创建的模拟对象:
# create your mock object
self.mock_stuff_obj = Mock()
self.my_class.return_value = self.mock_stuff_obj
现在,所有的测试方法可以简单地在所有使用self.my_class
和self.mock_stuff_obj
你的电话。
谢谢idjaw。我后来开始做一些这样的事情,但这仍然非常有用,谢谢! –
Doh!我花了很长时间看着我认为我做错了嘲笑,我错过了那个愚蠢的错误!谢谢Jared。 –