Как использовать assertRaises в пробном случае с использованием inlineCallbacks

Я пытаюсь выяснить, как написать тестовый пример, который утверждает, что исключение создано.

В настоящее время у меня есть 2 простых метода тестирования (успех и сбой). Каждый метод возвращает отложенную, которая уже была либо callback'd, либо errback'd. Тестирование метода успеха отлично работает. При тестировании метода отказа я ожидаю, что смогу утверждать, что было создано исключение (с использованием assertRaises).

Однако тестовый случай терпит неудачу, и я получаю:

twisted.trial.unittest.FailTest: ConnectionRefusedError not raised (<Deferred at 0x920e28c current result: <twisted.python.failure.Failure <class 'twisted.internet.error.ConnectionRefusedError'>>> returned)

Код выглядит следующим образом:

from twisted.trial.unittest import TestCase
from twisted.internet.defer import inlineCallbacks, succeed, fail
from twisted.internet.error import ConnectionRefusedError

class MyObject:
    def success(self):
        return succeed(True)

    def failure(self):
        return fail(ConnectionRefusedError())


class TestErrBack(TestCase):
    def setUp(self):
        self.o = MyObject()

    @inlineCallbacks
    def test_success(self):
        result = yield self.o.success()
        self.assertTrue(result)

    @inlineCallbacks
    def test_failure(self):
        # this test case is failing !
        yield self.assertRaises(ConnectionRefusedError, self.o.failure)

Я использую правильный подход в test_failure? Я могу использовать try... поймать вызов self.o.failure, но я не думаю, что этот подход так же хорош, как использование assertRaises.

Ответ 1

Вместо этого используйте TestCase.assertFailure:

yield self.assertFailure(self.o.failure(), ConnectionRefusedError)

Начиная с Twisted 12.3, существует также TestCase.failureResultOf помощник:

self.failureResultOf(self.o.failure()).trap(ConnectionRefusedError)

И начиная с 13.1 этот API принимает дополнительный аргумент и выполняет проверку типов для вас:

self.failureResultOf(self.o.failure(), ConnectionRefusedError)

Это полезно для тестов, в которых вы знаете, что Deferred уже запущен с результатом. Если Deferred не имеет результата сбоя во время вызова, failureResultOf вызывает исключение для проверки, вместо того, чтобы возвращать сбой.

Это будет отлично работать для вашего примера кода и должно быть применимо к большинству модульных тестов. Если вы используете пробную версию для написания функциональных или интеграционных тестов, в которых происходит фактическая асинхронная работа, и вы не знаете, когда будет срабатывать Deferred, тогда вам нужно придерживаться первого API, assertFailure.