2016-06-16 7 views
4

ich Einheit bin versucht, ein Stück Code testen:Mock_open CSV keine Daten Datei nicht immer

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]) 

unter Verwendung mock_open wie 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')) 

Das Problem, das ich in laufen lasse, ist, dass ich Erhalte keine Daten beim Ausführen von csv.reader. Wenn ich results_file.readlines() ausführe, bekomme ich "test, test2, test3, test4", was bedeutet, dass mock_open korrekt funktioniert. Aber wenn ich csv.reader (results_file) starte, verliere ich alle Daten.

+0

Ich denke, das ist, weil die CSV ist eigentlich eine _csv.c, ein kompiliertes c-Modul, so dass es aussieht, als ob die Mocks nicht übertragen werden? – nadersoliman

Antwort

1

Das hat mich auch wirklich, und war ein Albtraum zu lokalisieren. Um Ihre Beispielcode zu verwenden, funktioniert diese

results_data = list(csv.reader(results_file.read())) 

und das funktioniert

results_data = list(csv.reader(results_file.readlines())) 

aber das funktioniert nicht

results_data = list(csv.reader(results_file)) 

mit Python 3.4.

Es scheint entgegen der dokumentierten Schnittstelle von csv.reader so vielleicht ein Experte kann warum warum.

1

Dies ist, weil mock_open nicht jede Funktion implementiert, die eine Datei hat, und vor allem nicht einige der, die csv benötigt.

mock_open implementiert die Methoden read(), readline() und readlines() und arbeitet sowohl als eine Funktion, und wenn sie als Kontextmanager (https://docs.python.org/3/library/unittest.mock.html#mock-open), während csv.reader Arbeiten mit ...

jedes Objekt, das unterstützt das Iterator-Protokoll genannt, und gibt eine Zeichenfolge jedes Mal seine __next__() Methode aufgerufen wird - Dateiobjekte und Listenobjekte sind sowohl geeignet

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

Beachten Sie, dass mock_open nicht die __next__() Methode nicht implementiert, und nicht StopIteration nicht erhöhen, wenn das Ende erreicht ist, so wird es nicht mit csv.reader arbeiten.

Die Lösung, wie @Emily in ihrer Antwort darauf hinweist, besteht darin, die Datei in eine Liste ihrer Zeilen umzuwandeln. Dies ist möglich, weil mock_openreadlines() implementiert und die resultierende Liste ist geeignet zum Lesen in csv.reader, wie die Dokumentation sagt.