wake-up-neo.com

Mock-Attribute in Python mock?

Ich habe eine ziemlich schwierige Zeit mit mock in Python:

def method_under_test():
    r = requests.post("http://localhost/post")

    print r.ok # prints "<MagicMock name='post().ok' id='11111111'>"

    if r.ok:
       return StartResult()
    else:
       raise Exception()

class MethodUnderTestTest(TestCase):

    def test_method_under_test(self):
        with patch('requests.post') as patched_post:
            patched_post.return_value.ok = True

            result = method_under_test()

            self.assertEqual(type(result), StartResult,
                "Failed to return a StartResult.")

Der Test gibt tatsächlich den richtigen Wert zurück, aber r.ok ist ein Mock-Objekt, nicht True. Wie verspotten Sie Attribute in der mock -Bibliothek von Python?

58
Naftuli Kay

Sie müssen return_value und PropertyMock verwenden:

with patch('requests.post') as patched_post:
    type(patched_post.return_value).ok = PropertyMock(return_value=True)

Dies bedeutet: Wenn Sie requests.post Aufrufen, setzen Sie für den Rückgabewert dieses Aufrufs ein PropertyMock für die Eigenschaft ok, um den Wert True zurückzugeben.

69
Simeon Visser

Eine kompakte und einfache Möglichkeit ist die Verwendung von new_callablepatch 's Attribut, um patch zu zwingen, PropertyMock anstelle von MagicMock zu verwenden, um das Scheinobjekt zu erstellen. Die anderen an patch übergebenen Argumente werden verwendet, um ein PropertyMock -Objekt zu erstellen.

with patch('requests.post', new_callable=PropertyMock, return_value=True) as mock_post:
    """Your test"""
13
Michele d'Amico

Mit der Mock-Version '1.0.1' wird die in der Frage erwähnte einfachere Syntax unterstützt und funktioniert so wie sie ist!

Beispielcode aktualisiert (py.test wird anstelle von unittest verwendet):

import mock
import requests


def method_under_test():
    r = requests.post("http://localhost/post")

    print r.ok

    if r.ok:
        return r.ok
    else:
        raise Exception()


def test_method_under_test():
    with mock.patch('requests.post') as patched_post:
        patched_post.return_value.ok = True

        result = method_under_test()
        assert result is True, "mock ok failed"

Führen Sie diesen Code aus mit: (Stellen Sie sicher, dass Sie pytest installieren)

$ py.test -s -v mock_attributes.py 
======= test session starts =======================
platform linux2 -- Python 2.7.10 -- py-1.4.30 -- pytest-2.7.2 -- /home/developer/miniconda/bin/python
rootdir: /home/developer/projects/learn/scripts/misc, inifile: 
plugins: httpbin, cov
collected 1 items 

mock_attributes.py::test_method_under_test True
PASSED

======= 1 passed in 0.03 seconds =================
9
howaryoo