我想测试一个方法,无论它是否调用临时内部对象的特定方法。(ConfigParser.read)
所以对象是在内部创建的,并且在方法退出后它不能从外部访问。
使用python 2.7
在foobar.py import ConfigParser
class FooBar:
def method(self, filename):
config=ConfigParser.ConfigParser()
config.read(filename)
do_some_stuff()
我想测试是否配置。
据我所知,补丁装饰器是为此制作的,但不幸的是,测试用例接收的MagicMock对象与内部创建的MagicMock对象不同,并且我无法接近方法内部的对象。
我试过了:
class TestFooBar(TestCase):
def setUp(self):
self.myfoobar = FooBar()
@mock.patch('foobar.ConfigParser')
def test_read(self,mock_foobar):
self.myfoobar.method("configuration.ini")
assert mock_foobar.called # THIS IS OKAY
assert mock_foobar.read.called # THIS FAILS
mock_foobar.read.assert_called_with("configuration.ini") # FAILS TOO
问题是:- mock_foobar在self.myfoobar.method创建ConfigReader之前创建。-当调试mock_foobar有关于之前调用的内部数据,但没有"read"属性(内部MagicMock模拟read方法)
当然,一种方法是重构并给.read()或init()一个ConfigReader对象,但是更改代码并不总是可能的,我想掌握方法的内部对象而不触及被测试的模块。
你很接近了!问题是,您正在模拟类,但随后您的测试检查是否在该模拟类上调用了read() -但实际上您希望在调用类时返回的实例上调用read()。下面的工作-我发现第二个测试比第一个更可读,但它们都工作:
import ConfigParser
from unittest import TestCase
from mock import create_autospec, patch, Mock
class FooBar(object):
def method(self, filename):
config=ConfigParser.ConfigParser()
config.read(filename)
class TestFooBar(TestCase):
def setUp(self):
self.myfoobar = FooBar()
@patch('ConfigParser.ConfigParser')
def test_method(self, config_parser_class_mock):
config_parser_mock = config_parser_class_mock.return_value
self.myfoobar.method("configuration.ini")
config_parser_class_mock.assert_called_once_with()
config_parser_mock.read.assert_called_once_with("configuration.ini")
def test_method_better(self):
config_parser_mock = create_autospec(ConfigParser.ConfigParser, instance=True)
config_parser_class_mock = Mock(return_value=config_parser_mock)
with patch('ConfigParser.ConfigParser', config_parser_class_mock):
self.myfoobar.method("configuration.ini")
config_parser_class_mock.assert_called_once_with()
config_parser_mock.read.assert_called_once_with("configuration.ini")