Python повертає об'єкт MagicMock замість return_value


86

У мене є файл python, a.pyякий містить два класи Aта B.

class A(object):
    def method_a(self):
        return "Class A method a"

class B(object):
    def method_b(self):
        a = A()
        print a.method_a()

Я хотів би пройти тестування method_bв класі B, глузуючи A. Ось вміст файлу testa.pyдля цієї мети:

import unittest
import mock
import a


class TestB(unittest.TestCase):

    @mock.patch('a.A')
    def test_method_b(self, mock_a):
        mock_a.method_a.return_value = 'Mocked A'
        b = a.B()
        b.method_b()


if __name__ == '__main__':
    unittest.main()

Я сподіваюся отримати Mocked Aвихід. Але я отримую:

<MagicMock name='A().method_a()' id='4326621392'>

Де я роблю неправильно?


1
Під час тестування A()повертає return_valuefrom mock_A(звичайний MagicMock, оскільки ви ще нічого не вказали), який не є екземпляром класу A. Вам потрібно встановити, що return_valueце щось, що має визначене method_a.
jonrsharpe

3
mock_a.method_a.return_value = 'Знущаються над A' => mock_a (). method_a.return_value = 'Знущаються над A' повинні бути краще :)
Алі

@AliSAIDOMAR є точно правильним, це повернене значення із виклику mock_aповинно мати метод, а не mock_aсам.
jonrsharpe

1
@jonrsharpe. Дякуємо за пояснення. Я просто спробував. Обидва mock_a().method_a.return_value = 'Mocked A'і mock_a.return_value.method_a.return_value = 'Mocked A'працювали. Велике спасибі за ваші коментарі. Будь ласка, продовжуйте і поставте це як відповідь?
Мехді Джафарнія Джахромі

@MehdiJafarniaJahromi велике спасибі!
Ніакрос,

Відповіді:


96

Коли ви @mock.patch('a.A')замінюєте клас Aу тестованому коді на mock_a.

У B.method_bвас тоді встановлено a = A(), що зараз a = mock_a()- тобто aє return_valueз mock_a. Оскільки ви не вказали це значення, воно є звичайним MagicMock; це також не налаштовано, тому ви отримуєте відповідь за замовчуванням (ще одну MagicMock) при виклику методів на ньому.

Замість цього, ви хочете налаштувати від мати відповідний метод, який ви можете зробити або як:return_valuemock_a

mock_a().method_a.return_value = 'Mocked A' 
    # ^ note parentheses

або, можливо, більш явно:

mock_a.return_value.method_a.return_value = 'Mocked A'

Ваш код працював би у випадку a = A(присвоєння класу, а не створення екземпляра), оскільки тоді a.method_a()це спричинило б ваш макетний метод.


4
Приголомшливо Ти мене вразив.
Vishal

Привіт @jonrsharpe, я використовую панд dataframe з df.columns , щоб перевірити мій , якщо умова. Він не використовує дужки (тобто він не викликається). Що мені робити, щоб повернути список у такому випадку. Дякую!
imsrgadich

@imsrgadich зробити вам потрібен макет для цього? Просто побудуйте відповідний фрейм даних, розгляньте його як тестове значення.
jonrsharpe

@jonrsharpe так, я міг би це зробити, але я також виконую df.drop у своєму методі, що викликається, який мені потрібно стверджувати, і більше, що я не повертаю фрейм даних назад із викликаного методу. Це створює проблему. Я знайшов спосіб, mock_data.configure_mock(columns='my_column')який вирішує це. Дякую за відповідь. (посилання: bradmontgomery.net/blog/how-world-do-you-mock-name-attribute )
imsrgadich

Здається, це не працює, коли ви знущаєтесь над двома моделями SQLAlchemy в одному тесті. Перший працює нормально, але другий поверне MagicMock незалежно від того, що ви визначили.
Юха Унтінен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.