You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django单元测试为何无法捕获抛出的DoesNotExist异常?

问题出在这儿!

哦,我一眼就发现问题所在了——你的read_list静态方法自己把异常吃掉了,所以测试代码根本抓不到它!

看你写的read_list方法:

@staticmethod
def read_list(list_id, list_name, owner, list_type):
    try:
        return List.objects.get(pk=list_id, name=list_name, owner=owner, type=list_type)
    except List.DoesNotExist:
        return None  # 重点在这里!你捕获了异常,然后返回了None,没有把异常抛出去

当List.objects.get()找不到匹配的记录时,确实会抛出List.DoesNotExist,但这个异常刚冒头就被except块接住了,方法最终只会返回None,不会把异常传递到测试代码里。这就是为什么你在断点里能看到异常被抛出,但测试却提示“AssertionError: DoesNotExist not raised”——因为异常根本没走出read_list方法。

另外还有个小错误:你的测试代码里调用的是List.read_list(),但这个静态方法是定义在ListType类里的!你应该调用ListType.read_list(),不然运行时会报AttributeError(可能你实际代码里写对了,但测试里手滑写错了)。

两种解决思路,看你想要哪种行为

思路1:让方法抛出异常(如果这是你期望的设计)

如果你希望read_list在找不到记录时向外抛出异常,那去掉方法里的try-except块就行:

@staticmethod
def read_list(list_id, list_name, owner, list_type):
    # 直接返回,找不到就抛出异常
    return List.objects.get(pk=list_id, name=list_name, owner=owner, type=list_type)

或者如果需要在捕获异常后做些额外处理(比如打日志),再重新抛出:

@staticmethod
def read_list(list_id, list_name, owner, list_type):
    try:
        return List.objects.get(pk=list_id, name=list_name, owner=owner, type=list_type)
    except List.DoesNotExist:
        # 这里可以加日志或其他逻辑
        raise  # 重新抛出异常,让外部测试能捕获到

这样你的原测试代码就能正常捕获到List.DoesNotExist了。

思路2:修改测试,验证返回None(如果方法设计就是返回None)

如果read_list的预期行为就是“找不到就返回None”,那测试应该验证这个返回值,而不是去抓异常:

def test_read_list_exc(self):
    uf = UserFactory()
    lt = ListType.objects.get(type='Member')
    ListFactory(owner=uf, type=lt, name='foo')
    # 注意:这里要调用ListType.read_list,不是List.read_list
    result = ListType.read_list(999, 'bar', uf, lt)
    self.assertIsNone(result)
总结一下

你当前测试失败的核心原因是方法内部捕获了异常并返回None,没有向外抛出,同时测试里还存在方法调用对象的错误。选一个符合你业务需求的思路调整代码就好啦~

内容的提问来源于stack exchange,提问作者Jim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:18:45