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
相关产品推荐
相关产品推荐

