我正在尝试对一段代码进行单元测试:
def _parse_results(self, file_name):
results_file = open(file_name)
results_data = list(csv.reader(results_file))
index = len(results_data[1])-1
results_file.close()
return float(results_data[1][index])
使用mock_open如此:
@mock.patch('path.open', mock.mock_open(read_data='test, test2, test3, test4'))
def test_parse_results(self):
cut = my_class(emulate=True)
self.assertEqual(VAL, cut._parse_results('file'))
我遇到的问题是我在运行csv.reader时没有得到任何数据。如果我运行results_file.readlines(),我会得到test,test2,test3,test4'这意味着mock_open正常工作。但是当我运行csv.reader(results_file)时,我丢失了所有数据。
答案 0 :(得分:4)
这是因为mock_open
没有实现文件的所有功能,特别是csv
不需要的功能。
mock_open
实现方法read()
,readline()
和readlines()
,并且作为函数和作为上下文管理器(https://docs.python.org/3/library/unittest.mock.html#mock-open)调用时,而csv.reader
适用于......
任何支持迭代器协议的对象,每次调用
__next__()
方法时返回一个字符串 - 文件对象和列表对象都适合
请注意,mock_open
没有实现__next__()
方法,并且在达到目标时不会提升StopIteration
,因此它不会工作与csv.reader
。
正如@Emily在她的回答中指出的那样,解决方案是将文件转换为其行列表。这是可能的,因为mock_open
实现了readlines()
,结果列表 适合阅读csv.reader
,如文档所述。
答案 1 :(得分:2)
这真的让我受益匪浅,并且是一场噩梦。要使用您的示例代码,可以使用
results_data = list(csv.reader(results_file.read()))
这是有效的
results_data = list(csv.reader(results_file.readlines()))
但这不起作用
results_data = list(csv.reader(results_file))
使用Python 3.4。
这似乎与csv.reader
的文档化界面相反,所以也许专家可以详细说明原因。