sag*_*ism 9 python unit-testing mocking python-2.7
我有这种设置,我正在测试一个使用另一个类的类,我想模仿后者,所以我只测试第一个类本身.
nuclear_reactor.py:
class NuclearReactor():
def __init__(self):
print "initializing the nuclear reactor"
def start(self):
print "starting the nuclear reactor"
Run Code Online (Sandbox Code Playgroud)
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()
Run Code Online (Sandbox Code Playgroud)
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()
Run Code Online (Sandbox Code Playgroud)
我想测试的是NuclearReactor.start被调用,但是当我运行它时,我得到:
manager creating the nuclear reactor
manager starting the nuclear reactor
manager starting the nuclear reactor
[call(), call().start(), call().start()]
0
Run Code Online (Sandbox Code Playgroud)
我完全理解,因为它start是实例的属性,而不是类的属性,我可以解析mock_calls,但是没有更好的方法来检查实例化的模拟类的调用是什么?
我可以使用依赖注入NuclearManager来传递一个模拟NuclearReactor,但我想有一种替代方法只使用mock.
您确实在测试是否start已直接在类上调用,而您的代码却没有.您可以直接在实例上测试该方法; 记住通过调用类生成实例:
print mock_reactor.return_value.calls
print mock_reactor.return_value.start.call_count
Run Code Online (Sandbox Code Playgroud)
该Mock.return_value属性是对模拟类的调用的结果,因此是实例.
你也可以调用 mock.默认情况下,Mocks在调用时总是返回完全相同的对象,一个表示该返回值的新模拟:
print mock_reactor().calls
print mock_reactor().start.call_count
Run Code Online (Sandbox Code Playgroud)
调用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()
Run Code Online (Sandbox Code Playgroud)
我在这里用它作为装饰者; 当test()调用函数时,mock被放置到位,当函数退出时,它会被再次删除.您还可以使用patch()上下文管理器来更精细地限制补丁的范围.
此外,对于像这样的单元测试,请使用unittest库:
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()
Run Code Online (Sandbox Code Playgroud)
这使您可以将测试适合更大的测试套件,启用和禁用测试,以及与其他测试工具集成.
| 归档时间: |
|
| 查看次数: |
5600 次 |
| 最近记录: |