【问题标题】:testing new operator fail测试新操作员失败
【发布时间】:2012-09-16 09:19:03
【问题描述】:

我创建了一个类,其中的构造函数中有一些 new 运算符。我已经在构造函数中创建了守卫来管理失败的新运算符,但现在我想测试它。

例如,我有一个这样的构造函数:

Function::Function()
{
  try
  {
    m_pxArgument = new Argument();
  }
  catch(std::bad_alloc)
  {
    throw MemoryException();
  }
}

是否可以创建一个测试来告诉新操作员失败,以测试我的 catch 代码?

【问题讨论】:

  • 我不是专业程序员,但我认为最好在构造函数之外使用try...
  • Argument 是你的类/结构吗?
  • 这只是一个例子,但是try语句必须留在里面,因为真正的类更复杂,我想处理库特定的异常。在这种情况下,std::bad_alloc 是一个有效的异常,但在我看来,它是由内部管理抛出的,这并不好。用户必须对类内部和内部异常一无所知。
  • 参数是标准的。我有另一个构造函数,我在其中指定对象必须使用的 Argument(),但在我的实现中可以使用默认值。

标签: c++ unit-testing boost boost-test


【解决方案1】:

如果 Argument 是您的类/结构 - 那么在此类中定义 operator new 仅用于 UT 目的。

class Argument {
//...
#ifdef UNIT_TEST
   static bool& failNew() { static bool failNew = false; return failNew; }
   void* operator new(size_t size)
   {
       if (!failNew())
         return ::operator new (size);
       failNew() = false;       
       throw std::bad_alloc("Argument");
   }
#endif
};

每次需要分配失败时,只需设置Argument::failNew() = true;

【讨论】:

  • 谢谢,这是一个很好的建议。我会试试看,如果它对我有用,我会告诉你。
【解决方案2】:

要进行这样的测试,您需要为您的class Argument 重载operator new,然后在您的测试用例中提供一个定义。但是,由于在运行时无法轻松交换,您可能需要单独的测试程序。

如果你是我的 C++ 学生,我会首先问,为什么你使用 new 和 a 可能是“裸”指针成员,无论如何都是可变的。第一种选择是创建一个 Argument 类型的成员变量并跳过显式堆分配。如果您真的需要现代代码中的动态分配,我建议使用shared_ptr<Argument> 和 Function::Function():m_pxArgument(make_shared()){}

我想问的第二个问题是,为什么要将std::bad_alloc 转换为您自己的异常类型,以及是否需要在构造函数中完成。 std::bad_alloc 是您实际遇到的情况的标准化例外,如果发生这种情况,生活通常会很糟糕,以至于您的小过程无法恢复(参见 Charles Weir 和 James Noble 的模式“Captain Oates”)。

【讨论】:

  • 嗨。起初,正如我所说,这只是一个例子。我的真实课程有点复杂,需要 new 运算符。但我会检查 share_ptr,谢谢你的建议。对于您的第二个答复,我想这样做是因为我想为库提供统一的异常管理,在这种情况下,我认为首选通用内存异常,因为它没有提供有关内部实现的详细信息,这可能会改变随着时间的推移。
猜你喜欢
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 2020-10-26
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多