9

我正在编写单元测试并试图覆盖我的所有代码。

我的代码中有这样的内容:

template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
    try 
    {
        return boost::lexical_cast<std::string, ValueType>(v);
    }
    catch(boost::bad_lexical_cast const& e)
    {
        LOG_ERR("Fail to cast %s to string", e.source_type().name);
        return std::string();
    }
}

我正在阅读这些文档,但找不到有关何时可以引发异常的任何boost::lexical_cast信息std::string

你能帮我吗?

如果不可能,我会简单地删除这个 try-catch。如果可能的话,我更愿意在单元测试中涵盖这一点。

4

3 回答 3

10

我想不出任何理由将词法转换为 string to throw bad_lexical_cast,除非使用用户定义的类型。如果ValueType流插入运算符可以在流上设置错误标志,那么这将导致bad_lexical_cast. 否则,不会。

catch就我个人而言,即使您只是转换像ints这样的内置插件,我也会保留它;lexical_cast如果您以某种方式更改它,或者如果有一些您和我都没有考虑过的极端情况,它不会受到伤害,并且可能会捕获错误;如果您不处理产生的异常,您将在运行时中止!

如果您担心异常的开销,您可以使用try_lexical_castinstead 并检查它是否返回true而不是捕获。但是,如果ValueType流插入运算符可以抛出,那么您仍然需要能够捕获该异常。

于 2019-05-01T11:56:15.590 回答
8

例如,如果用户定义的转换抛出:

enum class MyType {};

std::ostream& operator<<( std::ostream&, MyType const& )
{
    throw "error";
}

int main()
{
    try 
    {
        boost::lexical_cast< std::string >( MyType{} );
    }
    catch(...)
    {
        std::cout << "lexical_cast exception";
    }
}

由于您无法控制用户定义的转换引发的异常类型,因此捕获boost::bad_lexical_cast甚至还不够。您的单元测试必须捕获所有异常。

现场演示

于 2019-05-01T12:23:10.583 回答
1

唯一安全且永不过时的(例如,在更新后没有令人讨厌的意外)是用这样的东西(丑陋)损害你的代码:

template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
    try 
    {

#ifdef UNITTEST
      if (unittest == case_fail) {
        throw boost::bad_lexical_cast();
      }
#endif
        return boost::lexical_cast<std::string, ValueType>(v);
    }
    catch(boost::bad_lexical_cast const& e)
    {
        LOG_ERR("Fail to cast %s to string", e.source_type().name);
        return std::string();
    }
}

现在您应该能够达到约 100% 的代码覆盖率!

于 2019-05-01T12:12:52.050 回答