C++如何重构这个代码?

4

在我的测试代码中,我有很多地方都有下面的代码:

  //
  // Make a function call while expecting an exception should be thrown
  //
  bool exceptionThrown = false;
  try
  {
    expectNotEqual(someData, anotherData, methodName);
  }
  catch(std::logic_error&)
  {
    exceptionThrown = true;
  }
  if(!exceptionThrown)
    throw std::logic_error(methodName+"exception not thrown");

如果我能封装所有内容并做出以下操作,那将更易读、简洁:

  exceptionShouldBeThrown(expectNotEqual(someData, anotherData, methodName));

我不想使用宏...有人知道我如何用C++实现上述一行代码吗?


2
如果没有像Boost Bind这样的(好的)绑定系统,想要实现这一点是不可能的,除非使用宏。 - GManNickG
3
应该抛出异常吗?数值不相等?否定逻辑很伤脑筋。 - Frank Krueger
3
为什么不将 expectNotEqual 重写为返回一个值,而不是抛出异常? - Dmitry Brant
3
这是测试代码 - 作者试图确保当他传入无效输入时,他的方法会按预期抛出异常。显然有时会抛出异常,因此建议重写所有代码以避免抛出异常有些荒谬(即使在这种情况下可以这样做)。 - Cascabel
1
@Jefromi 理解了我的问题的原因!谢谢! - sivabudh
显示剩余3条评论
2个回答

11

我知道你说不要使用宏,但为什么?宏可以用来生成代码:

#define SHOULD_THROW(x, name) \
    { \
        bool didThrow = false; \
        try \
        { \
            x; \
        } \
        catch(...) { didThrow = true; } \
        \
        if (!didThrow) \
            throw std::logic_error(name " did not throw."); \
    }

SHOULD_THROW(expectNotEqual(someData, anotherData), "expectNotEqual")

如果你真的不想使用宏,你需要创建一个可调用对象来调用:

template <typename Func>
void should_throw(Func pFunc, const std::string& pName)
{
    bool didThrow = false;
    try
    {
        pFunc();
    }
    catch (...)
    {
        didThrow = true;
    }

    if (!didThrow)
        throw std::logic_error(pName + " did not throw.");
}

Boost Bind 可以帮助解决这个问题:

should_throw(boost::bind(expectNotEqual, someData, anotherData),
                "expectNotEqual");

当然,任何能够成为函数对象的东西都可以起作用,例如lambda等。但是如果Boost可用,只需使用他们的测试库

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test)
{
    BOOST_CHECK_THROW(expectNotEqual(someData, anotherData) , std::logic_error);
}

@GMan,我认为你关于宏的观点是正确的。也许我应该只使用宏。 - sivabudh
3
如果你有 Boost 库可用的话,我强烈建议使用它们的测试库。 - GManNickG
感谢您向我展示如何使用宏、Boost Bind和Boost测试的示例。 - sivabudh

2

异常主要用于处理一些意外情况,也就是那些在程序运行时不太可能出现的问题,例如内存溢出错误。而对于那些在运行时比较常见的情况,我们不应该使用异常进行测试。相反,可以通过 expectNotEqual 函数返回一个布尔值来判断测试结果是否成功:

if (expectNotEqual(someData, anotherData, methodName))
{
  //handle success
}
else
{
  //handle failure (which would include someData==anotherData)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接