Утверждение функции/метода не вызывается с использованием Mock
Я использую библиотеку Mock для тестирования своего приложения, но хочу утверждать, что некоторая функция не вызывалась. Mock docs рассказывают о методах типа mock.assert_called_with
и mock.assert_called_once_with
, но я не нашел ничего подобного mock.assert_not_called
или что-то связанное с проверкой mock было НЕ вызывается.
Я мог бы пойти с чем-то вроде следующего, хотя это не выглядит круто и не pythonic:
def test_something:
# some actions
with patch('something') as my_var:
try:
# args are not important. func should never be called in this test
my_var.assert_called_with(some, args)
except AssertionError:
pass # this error being raised means it ok
# other stuff
Любые идеи, как это сделать?
Спасибо за любую помощь:)
Ответы
Ответ 1
Это должно работать для вашего случая;
assert not my_var.called, 'method should not have been called'
Пример
>>> mock=Mock()
>>> mock.a()
<Mock name='mock.a()' id='4349129872'>
>>> assert not mock.b.called, 'b was called and should not have been'
>>> assert not mock.a.called, 'a was called and should not have been'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: a was called and should not have been
Ответ 2
Хотя старый вопрос, я хотел бы добавить, что в настоящее время библиотека mock
(backport of unittest.mock) поддерживает метод assert_not_called
.
Просто обновите свою версию;
pip install mock --upgrade
Ответ 3
Вы можете проверить атрибут called
, но если ваше утверждение не удастся, следующая вещь, которую вы хотите узнать, - это что-то о неожиданном вызове, поэтому вы можете также организовать эту информацию, которая будет отображаться с самого начала. Используя unittest
, вы можете проверить содержимое call_args_list
вместо:
self.assertItemsEqual(my_var.call_args_list, [])
Когда он терпит неудачу, он выдает следующее сообщение:
AssertionError: Element counts were not equal:
First has 0, Second has 1: call('first argument', 4)
Ответ 4
Когда вы проверяете использование наследований классов unittest.TestCase, вы можете просто использовать такие методы, как:
- assertTrue
- assertFalse
- assertEqual
и аналогичные (в документации python вы найдете все остальное).
В вашем примере мы можем просто утверждать, что свойство mock_method.called False, что означает, что этот метод не был вызван.
import unittest
from unittest import mock
import my_module
class A(unittest.TestCase):
def setUp(self):
self.message = "Method should not be called. Called {times} times!"
@mock.patch("my_module.method_to_mock")
def test(self, mock_method):
my_module.method_to_mock()
self.assertFalse(mock_method.called,
self.message.format(times=mock_method.call_count))
Ответ 5
Судя по другим ответам, никто, кроме @rob-kennedy, не говорил о call_args_list
.
Это мощный инструмент для того, чтобы вы могли реализовать точное противоречие MagicMock.assert_called_with()
call_args_list
- это список объектов call
. Каждый call
объект представляет собой вызов, сделанный на издеваемом вызываемом.
>>> from unittest.mock import MagicMock
>>> m = MagicMock()
>>> m.call_args_list
[]
>>> m(42)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42)]
>>> m(42, 30)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42), call(42, 30)]
Потребление объекта call
прост, так как вы можете сравнить его с кортежем длины 2, где первый компонент представляет собой кортеж, содержащий все позиционные аргументы связанного вызова, тогда как второй компонент является словарем ключевого слова аргументы.
>>> ((42,),) in m.call_args_list
True
>>> m(42, foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((42,), {'foo': 'bar'}) in m.call_args_list
True
>>> m(foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((), {'foo': 'bar'}) in m.call_args_list
True
Таким образом, способ решения конкретной проблемы OP -
def test_something():
with patch('something') as my_var:
assert ((some, args),) not in my_var.call_args_list
Обратите внимание, что таким образом, вместо того, чтобы просто проверять, был ли вызван вымышленный вызываемый вызов, через MagicMock.called
вы можете проверить, был ли он вызван с определенным набором аргументов.
Это полезно. Предположим, вы хотите протестировать функцию, которая принимает список и вызывать другую функцию, compute()
, для каждого из значений списка, только если они удовлетворяют конкретному условию.
Теперь вы можете mock compute
и проверить, было ли оно вызвано каким-то значением, но не на других.
Ответ 6
С помощью python >= 3.5
вы можете использовать mock_object.assert_not_called()
.