Ich habe eine Funktion, die ich Unit-Test enthält, ruft zwei andere Funktionen. Ich bin nicht sicher, wie ich beide Funktionen gleichzeitig mithilfe von Patch richtig verspotten kann. Ich habe unten ein Beispiel für das gegeben, was ich meine. Wenn ich Nosetests durchführe, sind die Tests erfolgreich, aber ich bin der Meinung, dass es einen saubereren Weg dafür geben muss, und ich verstehe das Stück in Bezug auf f.close () nicht wirklich.
Die Verzeichnisstruktur sieht folgendermaßen aus:
program/
program/
data.py
tests/
data_test.py
data.py:
import cPickle
def write_out(file_path, data):
f = open(file_path, 'wb')
cPickle.dump(data, f)
f.close()
data_test.py:
from mock import MagicMock, patch
def test_write_out():
path = '~/collection'
mock_open = MagicMock()
mock_pickle = MagicMock()
f_mock = MagicMock()
with patch('__builtin__.open', mock_open):
f = mock_open.return_value
f.method.return_value = path
with patch('cPickle.dump', mock_pickle):
write_out(path, 'data')
mock_open.assert_called_once_with('~/collection', 'wb')
f.close.assert_any_call()
mock_pickle.assert_called_once_with('data', f)
Ergebnisse:
$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.008s
OK
Sie können Ihren Test vereinfachen, indem Sie den Patch Decorator verwenden und sie wie folgt verschachteln (standardmäßig handelt es sich um MagicMock
-Objekte):
@patch('cPickle.dump')
@patch('__builtin__.open')
def test_write_out(mock_open, mock_pickle):
path = '~/collection'
f = mock_open.return_value
f.method.return_value = path
write_out(path, 'data')
mock_open.assert_called_once_with('~/collection', 'wb')
mock_pickle.assert_called_once_with('data', f)
f.close.assert_any_call()
Aufrufe an eine Instanz von MagicMock
geben eine neue Instanz von MagicMock
zurück, sodass Sie überprüfen können, ob der zurückgegebene Wert wie jedes andere verspottete Objekt aufgerufen wurde. In diesem Fall ist f
ein MagicMock
mit dem Namen 'open()'
(versuchen Sie, f
zu drucken).
Zusätzlich zu der Antwort @Matti John können Sie auch patch
inside function test_write_out
:
from mock import MagicMock, patch
def test_write_out():
path = '~/collection'
with patch('__builtin__.open') as mock_open, \
patch('cPickle.dump') as mock_pickle:
f = mock_open.return_value
...
Hier ist ein einfaches Beispiel, wie man das Auslösen von ConflictError
in der Funktion create_collection
Mit Mock testet:
import os
from unittest import TestCase
from mock import patch
from ..program.data import ConflictError, create_collection
class TestCreateCollection(TestCase):
def test_path_exists(self):
with patch.object(os.path, 'exists') as mock_method:
mock_method.return_value = True
self.assertRaises(ConflictError, create_collection, 'test')
Bitte sehen Sie auch Mock Docs und Michael Foord's awesome Einführung in Mock .