Skip to main content
 首页 » 编程设计

python之无法通过 Python 中的 assertRaises 测试

2025年05月04日31artech

所以,我有世界上最微不足道的例子。这是我要测试的类(class):

# My_Class.py 
class My_Class(object):     
    @staticmethod      
    def doit(name, params): 
        try: 
            raise Exception("This is my error message") 
        except Exception: 
            print("Exception: I raised Exception") 

这是测试仪本身:

# test.py 
import unittest 
from My_Class import My_Class 
 
class Test_MyClass(unittest.TestCase): 
 
    def setUp(self): 
        self.my_class = My_Class()    
 
    def test_my_class(self): 
        name = "Abrakadabra" 
        params = {} 
        self.assertRaises(Exception, self.my_class.doit, name, params) 

这是我在控制台中看到的,当我运行我的 test.py 时:

$ nosetests test.py 
F 
====================================================================== 
FAIL: test_my_class (test.Test_MyClass) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
  File .... 
nose.proxy.AssertionError: Exception not raised by doit 
-------------------- >> begin captured stdout << --------------------- 
Exception: I raised Exception 
 
--------------------- >> end captured stdout << ---------------------- 
 
---------------------------------------------------------------------- 
Ran 1 test in 0.001s 
 
FAILED (failures=1) 

这真的很有趣,因为它是有争议的。一方面,测试说“Exception not raised by doit”,但它下面的一行清楚地打印出来自 Exception block 的消息。那么,我在这里做错了什么???谢谢!

请您参考如下方法:

直接回答你的问题,你收到这条消息的原因是因为这个断言:

self.assertRaises(Exception, self.my_class.doit, name, params) 

您正在测试以确保引发异常。但是你的 try/except 抑制了这一点。如果你真的删除你的 try/except 你的测试实际上会通过,因为现在你的方法会引发。

既然您不想这样做,您应该做的是在引发异常时测试您的方法的行为。最后,您要确保 print 方法在您的 except 中被调用。我在下面整理了一个示例来帮助理解这一点。

记住 @user2357112 提到的内容,这在单元测试时非常重要,这里有一个示例可以帮助扩展它,为您尝试做的事情提供实际用途:

让我们把一些方法放在一起:

def some_method(): 
    pass 

我们现在将其放入您定义的静态方法中:

# My_Class.py 
class My_Class(object):     
    @staticmethod      
    def doit(name, params): 
        try: 
            some_method() 
        except Exception: 
            print("Exception: I raised Exception") 

现在,当涉及到您的单元测试时,您想要测试方法doit 的行为。考虑到这一点,在这种情况下您要做的是测试 some_method 是否会引发异常,并且您将验证您的 doit 方法行为 引发的异常。

此时,我建议看一下 unittest 背后的文档和 mock为了更熟悉您可以通过测试做什么,但这里有一个使用模拟修补来测试代码在引发异常时的行为的示例:

@patch('builtins.print') 
@patch('__main__.some_method') 
def test_my_class(self, m_some_method, m_print): 
    name = "Abrakadabra" 
    params = {} 
    # have the side_effect raise the exception when some_method is called in doit 
    m_some_method.side_effect = Exception() 
 
    self.my_class.doit(name, params) 
 
    # check to make sure you caught the exception by checking print was called 
    self.assertEqual(m_print.call_count, 1) 

当你把它们放在一起时,下面是我在我这边运行的功能代码,你可以尝试了解发生了什么:

def some_method(): 
    pass 
 
# My_Class.py 
class My_Class(object):     
    @staticmethod      
    def doit(name, params): 
        try: 
            some_method() 
        except Exception: 
            print("Exception: I raised Exception") 
 
 
# test.py 
import unittest 
from mock import patch 
 
class Test_MyClass(unittest.TestCase): 
 
    def setUp(self): 
        self.my_class = My_Class() 
 
@patch('builtins.print') 
@patch('__main__.some_method') 
def test_my_class(self, m_some_method, m_print): 
    name = "Abrakadabra" 
    params = {} 
    m_some_method.side_effect = Exception() 
    self.my_class.doit(name, params) 
    self.assertEqual(m_print.call_count, 1) 
 
 
if __name__ == '__main__': 
    unittest.main()