如何在Django中正确使用assertRaises

问题描述 投票:0回答:4

我的模型中有以下验证函数:

@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')

这两个都不能正常工作。我做错了什么?

django python-unittest django-testing django-tests django-errors
4个回答
31
投票

您调用

assertRaises
的方式是错误的 - 您需要传递可调用的而不是调用函数本身,并将函数的任何参数作为参数传递给
assertRaises
。改为:

self.assertRaises(ValidationError, w.validate_kind, 'test')

8
投票

接受的答案不正确。

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')

3
投票

我会做:

with self.assertRaises(ValidationError, msg='Invalid question kind'):
    w.validate_kind('test')

自从问题最初提出以来,这很可能是 Python 中的一个变化。


0
投票

请勿使用

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 的测试文档

© www.soinside.com 2019 - 2024. All rights reserved.