Ist es möglich, einen Rückgabewert einer Funktion zu verspotten, die in einer anderen Funktion aufgerufen wird, die ich testen möchte? Ich möchte, dass die verspottete Methode (die in vielen Methoden, die ich teste, aufgerufen wird) bei jedem Aufruf meine angegebenen Variablen zurückgibt. Zum Beispiel:
class Foo:
def method_1():
results = uses_some_other_method()
def method_n():
results = uses_some_other_method()
Im Unit-Test möchte ich mock verwenden, um den Rückgabewert von uses_some_other_method()
so zu ändern , dass bei jedem Aufruf Foo
das zurückgegeben wird, was ich definiert habe@patch.object(...)
python
unit-testing
mocking
patch
mdoc-2011
quelle
quelle
Antworten:
Es gibt zwei Möglichkeiten, wie Sie dies tun können. mit patch und mit patch.object
Patch geht davon aus, dass Sie das Objekt nicht direkt importieren, sondern dass es von dem zu testenden Objekt wie im Folgenden verwendet wird
#foo.py def some_fn(): return 'some_fn' class Foo(object): def method_1(self): return some_fn()
#bar.py import foo class Bar(object): def method_2(self): tmp = foo.Foo() return tmp.method_1()
#test_case_1.py import bar from mock import patch @patch('foo.some_fn') def test_bar(mock_some_fn): mock_some_fn.return_value = 'test-val-1' tmp = bar.Bar() assert tmp.method_2() == 'test-val-1' mock_some_fn.return_value = 'test-val-2' assert tmp.method_2() == 'test-val-2'
Wenn Sie das zu testende Modul direkt importieren, können Sie patch.object wie folgt verwenden:
#test_case_2.py import foo from mock import patch @patch.object(foo, 'some_fn') def test_foo(test_some_fn): test_some_fn.return_value = 'test-val-1' tmp = foo.Foo() assert tmp.method_1() == 'test-val-1' test_some_fn.return_value = 'test-val-2' assert tmp.method_1() == 'test-val-2'
In beiden Fällen wird some_fn nach Abschluss der Testfunktion nicht verspottet.
Bearbeiten: Um mehrere Funktionen zu verspotten, fügen Sie der Funktion einfach weitere Dekoratoren hinzu und fügen Sie Argumente hinzu, um die zusätzlichen Parameter zu übernehmen
@patch.object(foo, 'some_fn') @patch.object(foo, 'other_fn') def test_foo(test_other_fn, test_some_fn): ...
Beachten Sie, dass der Dekorator umso früher in der Parameterliste steht, je näher er an der Funktionsdefinition liegt.
quelle
Dies kann mit so etwas geschehen:
# foo.py class Foo: def method_1(): results = uses_some_other_method() # testing.py from mock import patch @patch('Foo.uses_some_other_method', return_value="specific_value"): def test_some_other_method(mock_some_other_method): foo = Foo() the_value = foo.method_1() assert the_value == "specific_value"
Hier ist eine Quelle, die Sie lesen können: Patchen an der falschen Stelle
quelle
Lassen Sie mich klarstellen, wovon Sie sprechen: Sie möchten
Foo
in einem Testfall testen, der eine externe Methode aufruftuses_some_other_method
. Anstatt die eigentliche Methode aufzurufen, möchten Sie den Rückgabewert verspotten.class Foo: def method_1(): results = uses_some_other_method() def method_n(): results = uses_some_other_method()
Angenommen, der obige Code befindet sich im Modul
foo.py
unduses_some_other_method
ist im Modul definiertbar.py
. Hier ist das Unittest:import unittest import mock from foo import Foo class TestFoo(unittest.TestCase): def setup(self): self.foo = Foo() @mock.patch('foo.uses_some_other_method') def test_method_1(self, mock_method): mock_method.return_value = 3 self.foo.method_1(*args, **kwargs) mock_method.assert_called_with(*args, **kwargs)
Wenn Sie den Rückgabewert jedes Mal ändern möchten, wenn Sie verschiedene Argumente übergeben haben, wird
mock
Folgendes bereitgestelltside_effect
.quelle