web-dev-qa-db-fra.com

Le décorateur @Patch n'est pas compatible avec le luminaire Pytest

J'ai rencontré quelque chose de mystérieux, lors de l'utilisation du patch décorateur du package simulé intégré avec le montage pytest.

J'ai deux modules

    -----test folder
          -------func.py
          -------test_test.py

dans func.py:

    def a():
        return 1

    def b():
        return a()     

dans test_test.py

    import pytest
    from func import a,b
    from mock import patch,Mock

    @pytest.fixture(scope="module")
    def brands():
        return 1


    mock_b=Mock()

    @patch('test_test.b',mock_b)
    def test_compute_scores(brands):                 
         a()

Il semble que le patch décorer ne soit pas compatible avec le luminaire pytest. Quelqu'un a-t-il une idée de cela? Tnanks

31
Hello lad

J'ai eu le même problème et la solution pour moi était d'utiliser la bibliothèque fictive dans la version 1.0.1 (avant d'utiliser unittest.mock dans la version 2.6.0). Maintenant ça marche comme un charme :)

2
Konrad Kocik

Lors de l'utilisation de pytest fixture avec mock.patch, l'ordre des paramètres de test est crucial.

Si vous placez un paramètre de luminaire avant un paramètre simulé:

from unittest import mock

@mock.patch('my.module.my.class')
def test_my_code(my_fixture, mocked_class):

alors l'objet factice sera dans my_fixture et mocked_class sera recherché comme appareil:

fixture 'mocked_class' not found

Mais, si vous inversez l'ordre, placez le paramètre fixture à la fin:

from unittest import mock

@mock.patch('my.module.my.class')
def test_my_code(mocked_class, my_fixture):

alors tout ira bien.

23
bux

Depuis Python3., le module mock a été tiré dans le unittest bibliothèque. Il existe également un backport (pour les versions précédentes de Python) disponible en tant que bibliothèque autonome mock.

La combinaison de ces 2 bibliothèques au sein de la même suite de tests génère l'erreur mentionnée ci-dessus:

E       fixture 'fixture_name' not found

Dans l'environnement virtuel de votre suite de tests, exécutez pip uninstall mock, et assurez-vous que vous n'utilisez pas la bibliothèque rétroportée aux côtés de la bibliothèque principale non unifiée. Lorsque vous réexécutez vos tests après la désinstallation, vous verrez ImportErrors si tel était le cas.

Remplacez toutes les instances de cette importation par from unittest.mock import <stuff>.

5
The Aelfinn

Cela ne répond pas directement à votre question, mais il existe le plugin pytest-mock qui vous permet d'écrire ceci à la place:

def test_compute_scores(brands, mock):                 
     mock_b = mock.patch('test_test.b')
     a()
3
Bruno Oliveira

Espérons que cette réponse à une vieille question aidera quelqu'un.

Tout d'abord, la question n'inclut pas l'erreur, donc nous ne vraiment savons pas ce qui se passe. Mais je vais essayer de fournir quelque chose qui m'a aidé.

Si vous voulez un test décoré avec un objet patché, alors pour qu'il fonctionne avec pytest, vous pouvez simplement faire ceci:

@mock.patch('mocked.module')
def test_me(*args):
    mocked_module = args[0]

Ou pour plusieurs patchs:

@mock.patch('mocked.module1')
@mock.patch('mocked.module')
def test_me(*args):
    mocked_module1, mocked_module2 = args

pytest recherche les noms des appareils à rechercher dans la fonction/méthode de test. Fournir le *args L'argument nous donne une bonne solution de contournement pendant la phase de recherche. Donc, pour inclure un appareil avec des correctifs, vous pouvez le faire:

# from question
@pytest.fixture(scope="module")
def brands():
    return 1

@mock.patch('mocked.module1')
def test_me(brands, *args):
    mocked_module1 = args[0]

Cela a fonctionné pour moi en exécutant python 3.6 et pytest 3.0.6.

2
404