Reputation: 83
I am trying to unit test a piece of code:
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])
by using mock_open like so:
@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'))
The problem I am running into is that I do not get any data when running csv.reader. If I run results_file.readlines() I get 'test, test2, test3, test4' which means that mock_open is working properly. But when I run csv.reader(results_file) I lose all the data.
Upvotes: 9
Views: 3355
Reputation: 4138
This is because mock_open
doesn't implement every feature that a file has, and notably not some of the ones that csv
needs.
mock_open
implements the methods read()
, readline()
and readlines()
, and works both as a function and when called as a context manager (https://docs.python.org/3/library/unittest.mock.html#mock-open), whereas csv.reader
works with…
any object which supports the iterator protocol and returns a string each time its
__next__()
method is called — file objects and list objects are both suitable
Note that mock_open
doesn't implement the __next__()
method, and doesn't raise StopIteration
when the end is reached, so it won't work with csv.reader
.
The solution, as @Emily points out in her answer, is to turn the file into a list of its lines. This is possible because mock_open
implements readlines()
, and the resulting list is suitable for reading into csv.reader
as the documentation says.
Upvotes: 11
Reputation: 140
This really got me too, and was a nightmare to pinpoint. To use your example code, this works
results_data = list(csv.reader(results_file.read()))
and this works
results_data = list(csv.reader(results_file.readlines()))
but this doesn't work
results_data = list(csv.reader(results_file))
using Python 3.4.
It seems counter to the documented interface of csv.reader
so maybe an expert can elaborate on why.
Upvotes: 4