web-dev-qa-db-fra.com

Attributs de simulation dans Python maquette?

J'ai du mal à utiliser mock en 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.")

Le test renvoie en fait la bonne valeur, mais r.ok est un objet Mock, pas True. Comment se moquer des attributs dans la bibliothèque mock de Python?

58
Naftuli Kay

Vous devez utiliser return_value et PropertyMock :

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

Cela signifie: lors de l'appel de requests.post, sur la valeur de retour de cet appel, définissez un PropertyMock pour la propriété ok pour renvoyer la valeur True.

69
Simeon Visser

Une manière compacte et simple de le faire est d'utiliser new_callablepatch pour forcer patch à utiliser PropertyMock au lieu de MagicMock pour créer l'objet factice. Les autres arguments passés à patch seront utilisés pour créer un objet PropertyMock.

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

Avec la version simulée "1.0.1", la syntaxe plus simple mentionnée dans la question est prise en charge et fonctionne telle quelle!

Exemple de code mis à jour (py.test est utilisé à la place de unittest):

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"

Exécutez ce code avec: (assurez-vous d'installer pytest)

$ 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