Издевательство над функцией для создания исключения для проверки блока except


у меня есть функция (foo), которая вызывает другую функцию (bar). При вызове bar() выдает HttpError, Я хочу обрабатывать его специально, если код состояния 404, в противном случае повторно поднять.

я пытаюсь написать юнит-тестов по этой foo функция, издеваясь над вызовом bar(). К сожалению, я не могу получить издевательский звонок bar() чтобы вызвать исключение, которое поймано my except заблокировать.

вот мой код, который иллюстрирует моя проблема:

import unittest
import mock
from apiclient.errors import HttpError


class FooTests(unittest.TestCase):
    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock):
        barMock.return_value = True
        result = foo()
        self.assertTrue(result)  # passes

    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found')
        result = foo()
        self.assertIsNone(result)  # fails, test raises HttpError

    @mock.patch('my_tests.bar')
    def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error')
        with self.assertRaises(HttpError):  # passes
            foo()

def foo():
    try:
        result = bar()
        return result
    except HttpError as error:
        if error.resp.status == 404:
            print '404 - %s' % error.message
            return None
        raise

def bar():
    raise NotImplementedError()

я следовал Mock docs которые говорят, что вы должны установить side_effect на Mock экземпляр Exception класс, чтобы издевательская функция вызывала ошибку.

я также посмотрел на некоторые другие связанные с StackOverflow Q&As, и похоже, что я делаю то же самое, что они делают, чтобы вызвать и исключение, которое будет поднято их макетом.

  • https://stackoverflow.com/a/10310532/346561
  • как чтобы использовать Python Mock для создания исключения - но с Errno, установленным в заданное значение

почему задание side_effect на barMock не вызывая ожидаемого Exception быть воспитанным? Если я делаю что-то странное, как я должен идти о тестировании логики в моем except заблокировать?

1   62  

1 ответ:

ваш макет поднимает исключение просто отлично, но error.resp.status значение отсутствует. Вместо того, чтобы использовать return_value, просто сказать Mock это status атрибут:

barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')

дополнительные аргументы ключевого слова Mock() устанавливаются в качестве атрибутов на результирующий объект.

я поставил foo и bar определения my_tests модуль, добавленный в HttpError класс так что я мог бы использовать его тоже, и ваш тест затем может быть запущен успех:

>>> from my_tests import foo, HttpError
>>> import mock
>>> with mock.patch('my_tests.bar') as barMock:
...     barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
...     result = my_test.foo()
... 
404 - 
>>> result is None
True

вы даже можете увидеть print '404 - %s' % error.message line run, но я думаю, что вы хотели использовать error.content там вместо этого; это атрибут HttpError() устанавливает из второго аргумента, во всяком случае.