AssertRaises не удается, даже вызываемый вызывает требуемое исключение (python, unitest)
У меня есть следующая проверка тестового кода для повышения исключения в функции. Я ожидаю, что тест пройдет, но вместо этого указывается ошибка. Вот тестовый код:
import unittest
# define a user-defined exception
class MyException(Exception):
def __str__(self):
return repr("ERROR: Just raised my exception!")
# this is my main class with a method raising this exception
class MyMainObject(object):
def func(self):
raise MyException()
# the test class
class TestConfig(unittest.TestCase):
def test_1(self):
other = MyMainObject()
self.assertRaises(MyException, other.func())
# calling the test
if __name__ == '__main__':
unittest.main()
Когда other.func()
вызывается в инструкции assert, MyException
поднимается (можно легко проверить). Итак, тест assertRaises
должен пройти тест, так как other.func()
выходит с ошибкой MyException
, НО:
....
MyException: 'ERROR: Just raised my exception!'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
Я не вижу что-то не так, поэтому я был бы признателен за некоторые сведения об этой проблеме.
Ответы
Ответ 1
assertRaises
вызывает функцию для вас. Вызывая его самостоятельно, исключение возникает до того, как assertRaises
сможет его протестировать.
Измените свой код на:
self.assertRaises(MyException, other.func)
и он будет работать правильно. Кроме того, вы можете использовать assertRaises
в качестве менеджера контекста (python 2.7 и выше):
with self.assertRaises(MyException):
other.func()
Использование assertRaises
в качестве менеджера контекста имеет дополнительное преимущество: теперь вы можете получить экземпляр исключения и выполнить дополнительные тесты на нем:
with self.assertRaises(MyException) as raises_cm:
other.func()
exception = raises_cm.exception
self.assertEqual(exception.args, ('foo', 'bar'))
Ответ 2
Из-за правил языков аргументы оцениваются до ввода кода вызываемой функции (и это вообще хорошо). Поэтому assertRaises
не может перехватывать исключения, возникающие при оценке аргументов. Обходной путь (в нескольких API) заключается в том, что вы передаете вызываемые методы, такие как assertRaises
, чтобы они могли оценить его в месте, где они могут контролировать, и где они могут перехватывать исключения. Если весь аргумент является вызовом метода, магия связанных методов позволяет вам сказать это довольно элегантно, без lambda
или такой глупости:
self.assertRaises(MyException, other.func) # <- note, no parentheses after func