3

我有一个(类成员)函数,我希望避免由于歧义而导致应用程序崩溃。为此,我添加了一个 try catch 块,如下所示:

void getGene(unsigned int position){
     T val;
     try {
        val =  _genome.at(_isCircular ? position % _genome.size() : position);
     }
     catch (std::exception& e) {
         std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: " 
                   << e.what()  << std::endl;
         exit(1);
    }
    return val;
}

现在,我希望添加一个 Boost 单元测试,我想做类似的事情

BOOST_AUTO_TEST_CASE(nonCircularGenome_test){

   // set size to 10
   test.setSize(10);
   // set non circular
   test.setNonCircular();    

   // gene at site # 12 does not exist in a 10-site long genome, must throw an exception
   BOOST_CHECK_THROW(test.getGene(12), std::out_of_range);

问题是,我不能让这两个东西都起作用。try-catch 块在发布设置中运行良好。但是,只有当我删除 try-catch 块并让函数抛出异常时,此测试才有效。

什么是让这两个东西都工作的最佳方法,以便在旅途中提示用户正确的错误,而测试在调试时明确检查?一种方法是使用#ifdef/#endif DEBUG块,但我希望避免使用预处理器宏。

提前致谢,

尼基尔

4

1 回答 1

3

您似乎误解了异常的范围和目的——也许是一般的错误处理。

首先,你应该定义你的函数的先决条件是什么:getGene()总是期望position是一个有效的?它是否期望其客户永远不会提供无效的职位?

如果是这种情况,则提供无效头寸的客户端(即使客户端是测试例程)正在getGene()与定义。你不能测试未定义的行为,所以你应该删除你的测试。

另一方面,如果您的函数具有广泛的合同,即它允许客户端传递任何位置(甚至是无效的位置)并且 (a) 抛出异常或 (b) 在位置为时返回错误代码以传达失败无效,则该exit(1)行不应该存在,因为您正在退出程序并且控制不会转移回调用者。

一种可能性是在记录诊断后重新引发异常:

T getGene(unsigned int position){
    T val;
    try {
       val =  _genome.at(_isCircular ? position % _genome.size() : position);
    }
    catch (std::exception& e) {
        std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: " 
                  << e.what()  << std::endl;

        throw;
//      ^^^^^
    }
    return val;
}

如果您不需要打印诊断信息,只需让异常自然传播:

T getGene(unsigned int position){
    return _genome.at(_isCircular ? position % _genome.size() : position);
}
于 2013-06-17T16:18:07.860 回答