Python модуль pytest-mock, как проверить аргументы вызова метода, когда один класс вызывает другой экземпляр класса? - PullRequest
0 голосов
/ 20 января 2020

Я начал изучать юнит-тестирование с использованием pytest пару дней go и заинтересовался плагином pytest-mock (https://github.com/pytest-dev/pytest-mock).

Я был смог написать довольно много модульных тестов для проверки моего кода, но теперь я хотел бы проверить, как части моего кода взаимодействуют с другими объектами. Допустим, у меня есть класс B, который является классом, который я заинтересован в тестировании, у которого есть метод, который будет вызывать метод в классе A, и я хотел бы утверждать, что вызов метода был сделан с ожидаемыми аргументами, когда класс B позвоню в класс A.

Я собрал несколько примеров взлома (см. Ссылку ниже), которые выполнят работу, но, как вы можете видеть, это, вероятно, неправильный способ выполнения действий. Итак, мой вопрос, как это правильно обрабатывается с помощью модулей Python mock или pytest-mock? Также приветствуются ответы, не основанные на плагине pytest-mock.

В приведенном ниже коде это утверждение, которое меня не устраивает, поскольку я предпочел бы использовать существующий pytest-mock "assert_called_once_with (. ..) "- метод, но я просто не могу заставить его работать. Вся информация доступна в mock-объекте, но я не понимаю, как правильно использовать pytest-mock API в этом случае.

def test_how_class_b_interact_with_class_a(mocker):
    class A(object):
        def further_process_nbr(self, nbr):
            pass # don't care for the sake of this example

    class B(object):
        def __init__(self):
            self.a = A()

        def process_nbr(self, nbr):
            nbr += 2 # do something fancy with number and then have it further processed by object a
            return self.a.further_process_nbr(nbr)

    nbr = 4
    expected = 6

    # Prepare
    mock_a = mocker.patch.object(A, 'further_process_nbr', autospec=True)

    # Exercise
    B().process_nbr(nbr)

    # Assert
    assert mock_a.call_args_list[0].args[1] == expected # This is working, but not exactly a nice way
    # mock_a.assert_called_once_with(expected) something like this is basically what I would like to do

1 Ответ

0 голосов
/ 20 января 2020

На самом деле результат, который вы видите, верен:

assert (<a.A object at 0x000001628C6878B0>, 2) == (2,)

То, что вы видите в первом элементе кортежа, это параметр self, потому что вы высмеивали метод в классе, поэтому он также получает self.

Чтобы проверить, что с assert_called_once_with вы можете использовать mocker.ANY, который будет принимать все:

mock_a.assert_called_once_with(mocker.ANY, nbr)
...