测试实例中的方法是否已在mock中调用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了测试实例中的方法是否已在mock中调用相关的知识,希望对你有一定的参考价值。
我有这种设置,我正在测试一个使用另一个类的类,我想模仿后者,所以我只测试第一个类本身。
nuclear_reactor.py
:
class NuclearReactor():
def __init__(self):
print "initializing the nuclear reactor"
def start(self):
print "starting the nuclear reactor"
nuclear_manager.py
:
from nuclear_reactor import NuclearReactor
class NuclearManager():
def __init__(self):
print "manager creating the nuclear reactor"
self.reactor = NuclearReactor()
def start(self):
print "manager starting the nuclear reactor"
self.reactor.start()
test_nuclear_manager.py
:
from mock import Mock
import nuclear_manager
from nuclear_manager import NuclearManager
def test():
mock_reactor = nuclear_manager.NuclearReactor = Mock()
nuke = NuclearManager()
nuke.start()
nuke.start()
print mock_reactor.mock_calls
print mock_reactor.start.call_count
test()
我想测试的是调用NuclearReactor.start
,但是当我运行它时,我得到:
manager creating the nuclear reactor
manager starting the nuclear reactor
manager starting the nuclear reactor
[call(), call().start(), call().start()]
0
我完全理解,因为start
是实例的属性而不是类的属性,我可以解析mock_calls
,但是有没有更好的方法来检查实例化的模拟类的调用是什么?
我可以在NuclearManager
中使用依赖注入来传递一个模拟NuclearReactor
,但我想有一种替代方法只使用mock。
您确实在测试是否已在类上直接调用start
,而您的代码却没有。您可以直接在实例上测试该方法;记住通过调用类生成实例:
print mock_reactor.return_value.calls
print mock_reactor.return_value.start.call_count
Mock.return_value
attribute是对模拟类的调用的结果,所以实例。
你也可以调用mock。默认情况下,Mocks在调用时总是返回完全相同的对象,一个表示该返回值的新模拟:
print mock_reactor().calls
print mock_reactor().start.call_count
调用mock实例和mock实例return_value
属性的结果是同一个。
通过打印出对NuclearReactor
模拟的调用你已经走在了正确的道路上,你只是错过了在被调用的模拟器上调用start()
的细节,所以记录了call().start()
,而不是start()
。
您可能希望使用mock.patch()
来处理修补,而不是直接分配;这可以确保再次删除补丁,以便其他测试可以自行决定模拟的内容:
import mock
from nuclear_manager import NuclearManager
@mock.patch('nuclear_manager.NuclearReactor')
def test(mock_reactor):
nuke = NuclearManager()
nuke.start()
nuke.start()
instance = mock_reactor.return_value
assert instance.start.call_count == 2
instance.assert_called()
我在这里用它作为装饰者;当调用test()
函数时,mock被放置到位,当函数退出时,它会被再次删除。您还可以使用patch()
作为上下文管理器来更精细地限制补丁的范围。
此外,对于像这样的单元测试,请使用unittest
library:
import mock
import unittest
import nuclear_manager
class NuclearManagerTests(unittest.TestCase):
@mock.patch('nuclear_manager.NuclearReactor')
def test_start(self, mock_reactor):
nuke = NuclearManager()
nuke.start()
nuke.start()
instance = mock_reactor.return_value
self.assertEqual(instance.start.call_count, 2)
instance.assert_called()
if __name__ == '__main__':
unittest.main()
这使您可以将测试适合更大的测试套件,启用和禁用测试,以及与其他测试工具集成。
我使用模拟的方式是这样的:(代码是Python 3)
from unittest.mock import MagicMock
class NuclearManager():
def __init__(self, reactor):
print("manager creating the nuclear reactor")
self.reactor = reactor
def start(self):
print("manager starting the nuclear reactor")
self.reactor.start()
def test():
mock_reactor = MagicMock()
nuke = NuclearManager(mock_reactor)
nuke.start()
nuke.start()
# These two prints would actually be asserts of some sort
print(mock_reactor.mock_calls)
print(mock_reactor.start.call_count)
test()
输出:
manager creating the nuclear reactor
manager starting the nuclear reactor
manager starting the nuclear reactor
[call.start(), call.start()]
2
以上是关于测试实例中的方法是否已在mock中调用的主要内容,如果未能解决你的问题,请参考以下文章
jest中的mock,jest.fn()jest.spyOn()jest.mock()
jest中的mock,jest.fn()jest.spyOn()jest.mock()