Mock_open CSV文件没有获取任何数据

时间:2016-06-16 00:36:34

标签: python csv mocking

我正在尝试对一段代码进行单元测试:

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)时,我丢失了所有数据。

2 个答案:

答案 0 :(得分:4)

这是因为mock_open没有实现文件的所有功能,特别是csv不需要的功能。

mock_open实现方法read()readline()readlines(),并且作为函数和作为上下文管理器(https://docs.python.org/3/library/unittest.mock.html#mock-open)调用时,而csv.reader适用于......

  

任何支持迭代器协议的对象,每次调用__next__()方法时返回一个字符串 - 文件对象和列表对象都适合

     

- https://docs.python.org/3/library/csv.html#csv.reader

请注意,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的文档化界面相反,所以也许专家可以详细说明原因。