Исправление функции класса, которая вызывается из проверенного класса - PullRequest
1 голос
/ 01 мая 2019

Я прошу прощения за запутанный заголовок, я не был уверен, что есть лучший способ описать проблему.У меня есть библиотека Python со следующей структурой:

library/
  src/
    code/
      __init__.py
      baseclass.py
      helpers.py
      class1.py
    tests/
      __init__.py
      test_library.py

Я пытаюсь проверить функцию в классе в baseclass.py.Функция в классе в baseclass.py возвращает объекты класса из class1.py, как показано ниже: baseclass.py:

from class1 import DeviceClass

class LibraryBuilder:
    def __init__(self, user, password):
......

    def get_devices(self):
        devlist = helpers.call_api('api_url', 'post', header, json)
        #Return a list of dictionaries
        for dev in devlist:
            if dev = "DeviceType":
               return DeviceClass(dev, self)

test_library.py

import pytest
from unittest.mock import patch, Mock
from library.baseclass import LibraryBuilder
import library
from library.class1 import DeviceClass

class TestDeviceList(object):
    @pytest.fixture()
    def api_mock(self, caplog):
        self.mock_api_call = patch('library.helpers.call_api', autospec=True)
        self.mock_api = self.mock_api_call.start()
        self.mock_api.return_value.ok = True
        self.library_obj = library.baseclass.LibraryBuilder('sam@mail.com', 'pass')
        yield
        self.mock_api_call.stop()

    @patch.object('baseclass.class1', 'DeviceClass', autospec=True)
    def test_get_devices_all(self, caplog, dev_mock, api_mock):
        self.mock_api.return_value = return_dict
        devs = self.library_object.get_devices()
        dev_mock.assert_called_with(return_dict, self.library_object)

Тест не пройден, потому что 'device_object 'никогда не вызывается.Когда я выполняю отладку, я вижу, что созданный объект device_patch не является имитированным объектом, это фактический объект DeviceClass.

Я пытался сослаться на путь device_object к patch.object('library.baseclass', 'DeviceClass', autospec=True).Я пробовал варианты импортированных классов, потому что я думаю, что это связано с темой ниже, но я не могу понять, где я ошибаюсь: Почему патч python mock не работает?

Макет call_api работает как надо.Library_object возвращает действительный экземпляр класса, основанный на mock-переменной call_api return_value

Я просто рефакторинг кода из одного файла в эту конфигурацию, и тест проходил до этого.Любые идеи о том, что мне не хватает?

РЕДАКТИРОВАТЬ

Я отладил еще дальше, и я думаю, что это связано с DeviceClass наследование от DeviceBaseClass, так чтоdevice_class.py выглядит так:

class DeviceBaseClass(object):
    def __init__(self, details, manager):
         self.details = {}
..............
class DeviceClass(DeviceBaseClass):
    def __init__(self, details, manager):
        super(DeviceClass, self).__init__(details, manager)

, поэтому теперь я получаю сообщение TypeError: super() argument 1 must be type not MagicMock.Я предполагаю, так как я издеваюсь над DeviceClass, вызываемый класс вызывается в методе super ().Я видел несколько других постов по этому вопросу, но не нашел решения.Я что-то упускаю из виду или я совершенно не в курсе?

1 Ответ

0 голосов
/ 02 мая 2019

Наконец-то разобрался, так как я думал, что это местоположение импортированного модуля. Я испробовал все возможные варианты, и решение состоит в том, чтобы убедиться, что объект, к которому вы добавляете патч, вызывается. Я не знаю, почему я не видел это прошлой ночью !!

Исходный патч вызова был @patch('baseclass.class1', 'DeviceClass', autospec=True) Правильный патч @patch('baseclass.DeviceClass', autospec=True), как показано ниже

import pytest
from unittest.mock import patch, Mock
from library.baseclass import LibraryBuilder
import library
from library.class1 import DeviceClass

class TestDeviceList(object):
    @pytest.fixture()
    def api_mock(self, caplog):
        self.mock_api_call = patch('library.helpers.call_api', autospec=True)
        self.mock_api = self.mock_api_call.start()
        self.mock_api.return_value.ok = True
        self.library_obj = library.baseclass.LibraryBuilder('sam@mail.com', 'pass')
        yield
        self.mock_api_call.stop()

    @patch('Library.baseclass.DeviceClass', autospec=True)
    def test_get_devices_all(self, caplog, dev_mock, api_mock):
        self.mock_api.return_value = return_dict
        devs = self.library_object.get_devices()
        dev_mock.assert_called_with(return_dict, self.library_object)
...