我的模型中有以下验证函数:
@classmethod
def validate_kind(cls, kind):
if kind == 'test':
raise ValidationError("Invalid question kind")
我正在尝试测试如下:
w = Model.objects.get(id=1)
self.assertRaises(ValidationError, w.validate_kind('test'),msg='Invalid question kind')
我也尝试过:
self.assertRaisesRegex(w.validate_kind('test'),'Invalid question kind')
这两个都不能正常工作。我做错了什么?
您调用
assertRaises
的方式是错误的 - 您需要传递可调用的而不是调用函数本身,并将函数的任何参数作为参数传递给assertRaises
。改为:
self.assertRaises(ValidationError, w.validate_kind, 'test')
接受的答案不正确。
self.assertRaises()
不检查异常消息。
如果你想断言异常消息,你应该使用 self.assertRaisesRegex()。
self.assertRaisesRegex(ValidationError, 'Invalid question kind', w.validate_kind, 'test')
或
with self.assertRaisesRegex(ValidationError, 'Invalid question kind'):
w.validate_kind('test')
我会做:
with self.assertRaises(ValidationError, msg='Invalid question kind'):
w.validate_kind('test')
自从问题最初提出以来,这很可能是 Python 中的一个变化。
请勿使用
assertRaises
检查消息,因为它不会执行您认为的操作。
使用
assertRaisesMessage
代替:
with self.assertRaisesMessage(ValidationError, "Invalid question kind"):
w.validate_kind('test')
这将断言
"Invalid question kind"
是 in 错误消息,这通常就是您想要测试的全部内容(如果您想要更多控制,请使用 assertRaisesRegex
)。
为什么assertRaises很危险:
首先您需要知道有两种使用方法
assertRaises
(记录于此处)
1 - 通过传递可调用本身:
self.assertRaises(ValidationError, w.validate_kind, 'test')
callable后面的args/kwargs被传递给callable,所以没有办法检查消息。
2 - 通过用作上下文:
with self.assertRaises(ValidationError, msg='Invalid question kind'):
w.validate_kind('test')
这里
msg
只是简单地设置在捕获的异常上,以便稍后使用。 它不会检查函数引发的错误中的消息,因此即使消息不匹配,测试也会通过。
尝试看看:
def foo():
raise ValidationError('abc')
def test_foo():
with self.assertRaises(ValidationError, msg='xyz') as e:
foo()
print(e.exception, e.msg)
测试将通过,您将看到以下打印输出:
abc xyz
.
-------------------------------
Ran 1 test in 0.002s
这就是为什么在 TDD 中,他们总是建议你先编写一个失败的测试,然后再让它通过。
有关更多信息,请阅读 Django 的测试文档