Сбой функции с именем assertion в импровизированном импортированном классе - PullRequest
2 голосов
/ 30 апреля 2020

Я пытаюсь проверить ClassToTest в Python 3:

from path.to import ClassThatNeedsMocking

class ClassToTest:

  def __init__(self):
    pass

  def setup(self):
    foo = ClassThatNeedsMocking()
    foo.functionCall()

Этот класс реализован другим классом, поэтому я делаю простую настройку:

from some.other.path import ClassToTest

class ImplementingClass(ClassToTest):

  def __init__(self):
    super().__init__()

Я хочу смоделировать functionCall в ClassToTest с помощью следующего:

class TestClass:

  def testMethod(self):
    patch = mock.patch('path.to.ClassThatNeedsMocking')

    patcher = patch.start()
    patcher = MagicMock()
    patcher.functionCall = MagicMock()

    foo = ImplementingClass()
    foo.setup()

    # Results in an 'Expected to have been called once. Called 0 times.'
    patcher.functionCall.assert_called_once()

    patch.stop()

При печати foo.functionCall() в ClassToTest возвращается объект MagicMock, но все же утверждение выходит из строя. Это правильная настройка тестирования и чего мне здесь не хватает?

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Это то, что должно работать:

@mock.patch('path_to_class_to_test.ClassThatNeedsMocking')
def test_method(patched):
    foo = ImplementingClass()
    foo.setup()
    patched.return_value.functionCall.assert_called_once()

Во-первых, вам нужно пропатчить класс импортируемый в классе для тестирования (см. , где патчить ) , При использовании import from класс назначается новому объекту, который находится в модуле using, и это тот, который должен быть исправлен.

Во-вторых, вам нужен только пропатченный класс - не нужно повторять макет или запускать / останавливать патчер. Вы можете использовать декоратор (как я) или вызов функции, чтобы получить его. Исправление отменяется, как только вы выходите из области действия функции.

В-третьих, вы исправляете класс, но функция вызывается классом instance , который равен patched.return_value, поэтому Вы должны это проверить.

0 голосов
/ 30 апреля 2020

Последний тест, в котором используется ответ МрБина Бремена , более чистый. Для полноты здесь приведена ошибка в примере:

class TestClass:

  def testMethod(self):
    patch = mock.patch('path.to.ClassThatNeedsMocking')

    patcher = patch.start()
    #####################
    patcher = MagicMock()
    patcher.functionCall = MagicMock()
    #####################

    foo = ImplementingClass()
    foo.setup()

    patcher.functionCall.assert_called_once()

    patch.stop()

Возвращаемое значение вызова patch.start() должно использоваться непосредственно для подтверждения:

class TestClass:

  def testMethod(self):
    patch = mock.patch('path.to.ClassThatNeedsMocking')

    patcher = patch.start()

    foo = ImplementingClass()
    foo.setup()

    patcher.return_value.functionCall.assert_called_once()

    patch.stop()
...