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

为何触发ValueError后Python单元测试仍未检测到该异常?

问题:unittest无法检测到函数内捕获的ValueError

问题描述

我在完成Python课程作业时编写了get_funcs函数,当传入file_name为"test.csv"或"test"时会抛出ValueError,该异常会被函数内的try-except块捕获并通过print_log记录。但使用unittest的assertRaises进行测试时,明明能看到异常被抛出并记录,测试却失败,无法检测到这个ValueError。尝试将异常抛出移到try块外、新增ValueError捕获分支都无效,想知道原因。

函数代码

def get_funcs(funcs: dict, file_name: str, table_name: str) -> None:
    '''
    Read the given *.csv file, store the data inside the database and store the functions in a dict
    
    Args:
        functions dict: Dictionary to store the functions object
        file_name str: The file name of the csv-file with file extension
        table_name str: The name of the SQL table
    '''    
    
    global update_database

    try:
        if file_name == "test.csv" or file_name == "test":
            raise ValueError("The function for the test data is not neccessary.")
        elif file_name != "train.csv" and file_name != "train" and file_name != "ideal.csv" and file_name != "ideal":
            raise ValueError("Given a completly wrong / empty file or a directorys.")
        
        # store the complete path to the file in a variable
        complete_path = os.path.join(dataset_dir, file_name)
        # check file to be correct
        file_extension = os.path.splitext(file_name)[1]
        if file_extension == "":
            print_log(MessageType.Warn, "get_funcs", "Missing file extension. Added ".csv" automatically!")
            complete_path += ".csv"        
        if not os.path.exists(complete_path):
            raise FileNotFoundError()
        
        # read csv file and store it in a data frame
        data = pd.read_csv(complete_path, sep=",")
        print_log(MessageType.Info, "get_funcs", "Successfully read \"" + file_name + "\"!")
    except PermissionError as error:
        print_log(MessageType.Error, "get_funcs", "Cannot open the given csv file!")
        return
    except Exception as error:
        print_log(MessageType.Error, "get_funcs", error)
        return

测试代码

import main
import unittest

class UnitTestPythonTask(unittest.TestCase):
    def test_check_test_function(self):
        '''
        Checks the file validation of the given .csv files
        '''
        self.assertRaises(ValueError, main.get_funcs({}, "test.csv", "TestFunction"))

原因分析

核心问题在于函数内部已经捕获了抛出的ValueError,没有将异常传递到函数外部。assertRaises的作用是检测函数执行时向外抛出的异常,但你的get_funcs函数中,抛出的ValueError被最下方的except Exception块捕获,随后执行了print_log和return,异常根本没有传到函数外部,因此unittest无法检测到它。

哪怕你把异常抛出移到try块外,只要后续还是被try-except包裹(或者函数内其他except块捕获),异常依然不会向外传递;新增ValueError捕获分支但没有重新抛出的话,同样会拦截异常,导致unittest检测失败。

解决方案

方案1:让异常向外传递

修改函数的异常处理逻辑,在捕获ValueError后重新抛出,这样unittest就能检测到:

except PermissionError as error:
    print_log(MessageType.Error, "get_funcs", "Cannot open the given csv file!")
    return
except ValueError as error:
    print_log(MessageType.Error, "get_funcs", error)
    raise  # 重新抛出异常,让unittest捕获
except Exception as error:
    print_log(MessageType.Error, "get_funcs", error)
    return

方案2:不拦截特定的ValueError

如果不需要在函数内处理这类ValueError,可以直接移除对它的捕获,让它自然向外抛出:

try:
    # 原有逻辑...
except PermissionError as error:
    print_log(MessageType.Error, "get_funcs", "Cannot open the given csv file!")
    return
# 移除对Exception的捕获,或者调整捕获范围,排除测试用的ValueError

方案3:测试日志输出(不修改函数逻辑)

如果不想修改函数的异常处理逻辑,可以转而测试print_log是否输出了对应的错误信息。可以通过模拟print_log函数来验证:

from unittest.mock import patch

def test_check_test_function(self):
    with patch('main.print_log') as mock_print_log:
        main.get_funcs({}, "test.csv", "TestFunction")
        mock_print_log.assert_called_with(
            main.MessageType.Error, 
            "get_funcs", 
            "The function for the test data is not neccessary."
        )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:53:15