Я вижу ряд проблем в вашем тесте, в итоге вы не должны вносить исправления, и вы тестируете слишком мало.Позвольте мне заняться ими один за другим.
Не исправляйте
Действительно, это огромная возможность сделать ошибки или попасть в некоторые из многочисленных предостережений.Практически каждый урок начинается с использования исправлений для тестирования кода, который сложно протестировать.Но ваш код тестируемый, и он вам не нужен, это также будет работать:
def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(None, None)
self.assertEqual(handler.call_count, 2)
Проверьте аргументы, передаваемые в вызовах mocks
Ваш тест проверяет, что обработчик был вызвандважды, но не аргументы переданы.Вы бы предпочли проверить, что переданы правильные аргументы.
def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(None, None)
self.assertEqual(
handler.mock_calls,
[mock.call(None, None), mock.call(None, None)]
)
На самом деле проверьте аргументы
Сейчас мы проверяем, что None
передается обработчикам, но и событие, иbody - это None
, а все остальное тоже может быть None
, поэтому мы не знаем, действительно ли код делает правильный вызов.Лучше, если мы будем использовать разные уникальные значения для каждого аргумента.
def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(mock.sentinel.event, mock.sentinel.body)
self.assertEqual(
handler.mock_calls,
[mock.call(mock.sentinel.event, mock.sentinel.body),
mock.call(mock.sentinel.event, mock.sentinel.body)]
)
Тест с разными обработчиками
Наличие одного и того же обработчика дважды является угловым случаем.Даже если вы захотите сохранить этот тест (или изменить его; действительно ли вы хотите разрешить дублированные обработчики?), Вы действительно хотите протестировать общий случай, когда обработчики отличаются.
def test_handle(self):
handler1 = mock.Mock(name='handler1')
handler2 = mock.Mock(name='handler2')
messages = MessageHandler([handler1, handler2])
messages.handle(mock.sentinel.event, mock.sentinel.body)
handler1.assert_called_once_with(
mock.sentinel.event, mock.sentinel.body
)
handler2.assert_called_once_with(
mock.sentinel.event, mock.sentinel.body
)
Проверьте, чтообработчики вызываются по порядку
Если вы хотите утверждать, что вызовы сделаны по порядку, приведенного выше теста недостаточно.Это все равно пройдет, если вы измените порядок утверждений.Единственный известный мне способ проверить порядок вызова различных макетов - сделать их атрибутами одного и того же родительского макета.Это вовсе не делает меня счастливым, потому что тест касается объекта, не связанного с поведением, которое я хочу проверить, но, похоже, это единственный путь.
def test_handle(self):
handlers_parent = mock.Mock(name='handlers_parent')
handler1 = handlers_parent.handler1
handler2 = handlers_parent.handler2
messages = MessageHandler([handler1, handler2])
messages.handle(mock.sentinel.event, mock.sentinel.body)
self.assertEqual(
handlers_parent.mock_calls,
[mock.call.handler1(mock.sentinel.event, mock.sentinel.body),
mock.call.handler2(mock.sentinel.event, mock.sentinel.body)]
)