我有以下配置类:
class ConfigB(object):
Id = None
fileName = None
def __init__(self, file):
self.Id = self.searchForId(file)
self.fileName = file
在以下类中多次实例化并访问了属性:
from config.ConfigB import ConfigB
class FileRunner(object):
def runProcess(self, cfgA)
for file in cfgA.listFiles:
cfgB = ConfigB(file)
print(cfgB.Id)
print(cfgB.fileName)
为了测试它,我创建了以下测试类,我在其中模拟了FileRunner类的ConfigB:
import unittest
import unittest.mock imort MagicMock
import mock
from FileRunner import FileRunner
class TestFileRunner(unittest.TestCase):
@mock.patch('FileRunner.ConfigB')
def test_methodscalled(self, cfgB):
cfgA = Mock()
cfgA.listFiles = ['File1','File2']
cfgB().Id.side_effect = [1,2]
cfgB().fileName.side_effect = ['File1','File2']
fileRunner = FileRunner()
fileRunner.runProcess(cfgA)
我试图让cfgB的模拟为两个' Id'返回多个值。和' fileName'。如果我使用cfgB().fileName = 'File1'
,我可以让cfgB的模拟返回' File1'两次,但我更愿意,如果我可以迭代多个返回值。有什么可以做的吗?
*编辑:我想说明上述测试不能用于返回特定值,而是我得到以下输出:
<MagicMock name='cfgB().Id' id='160833320'>
<MagicMock name='cfgB().fileName' id='160833320'>
<MagicMock name='cfgB().Id' id='160833320'>
<MagicMock name='cfgB().fileName' id='160833320'>
答案 0 :(得分:1)
这里的问题是您实际上并没有按照预期的方式使用side_effect
。
根据文档here,side_effect
属性声明:
调用Mock时要调用的函数。见 side_effect属性。用于引发异常或动态 改变回报值。使用相同的参数调用该函数 作为模拟,除非它返回DEFAULT,否则返回此值 函数用作返回值。
这里要实现的关键是功能。这里的期望实际上是所谓的。实际上,您正在测试属性,并且不像函数一样调用属性,因此您实际上并没有正确配置测试以及使用这些side_effect调用的方式。
根据您要测试的内容,您应该采取稍微不同的方法。查看代码,在迭代ConfigB
时,您希望在循环内创建一个cfgA.listFiles
对象。因此,这表明您实际上希望控制side_effect
当您在测试中将ConfigB(file)
模拟为cfgB
时调用的cfgA.listFiles
。
此外,您正在传递从configB
迭代到listFiles
的文件名。因此,您只需将cfgA.listFiles = ['some_file_name_1', 'some_file_name_2']
设置为任意文件名列表:
cfgB
然后,您需要做的就是设置Mock
模拟的side_effect现在返回一个包含感兴趣属性的cfgB.side_effect = [
Mock(Id="some_id_1", fileName="some_filename_1"),
Mock(Id="some_id_2", fileName="some_filename_2")
]
对象,以便正确地进行测试,因此:
some_id_1
some_filename_1
some_id_2
some_filename_2
运行这些修改后,您将从代码中的print语句中产生以下结果:
side_effect
因此,正如您所看到的,现在我们已成功设置您的iterable以保存您要为测试设置的文件名。此外,ConfigB
现在可以在模拟class TestFileRunner(unittest.TestCase):
@mock.patch('FileRunner.ConfigB')
def test_methodscalled(self, cfgB):
cfgA = Mock()
cfgA.listFiles = ['some_file_name_1', 'some_file_name_2']
cfgB.side_effect = [
Mock(Id="some_id_1", fileName="some_filename_1"),
Mock(Id="some_id_2", fileName="some_filename_2")
]
fileRunner = FileRunner()
fileRunner.runProcess(cfgA)
时正确使用,以便现在返回正确的模拟配置对象,其中包含您可以在每次迭代中测试的属性。
以下是最终测试方法的全部内容:
java -cp /home/Blake Main arg1 arg2 arg3