【问题标题】:C++ unit test - Test class with throwed error in constructorC++ 单元测试 - 测试类在构造函数中抛出错误
【发布时间】:2020-11-20 12:09:02
【问题描述】:

我在使用不依赖于我的成员变量测试类时遇到问题。我的意思是该类包含一个包含来自其他文件的变量。这个类在构造函数中抛出错误(不管为什么)。然后我有一个使用这个变量的函数。那么我应该如何测试这个类呢?

// ** classForMe.h can't modify **
class ClassForMe
{
public:
  ClassForMe(){
    // not relevant what should be here but throw error in this case
    throw std::runtime_error("");
  }
  int getData()const {return data;}
...
private:
  int data;
};

包含我的课程的其他文件

// C.hpp
#include <classForMe.h>
class C
{
public:
  C():classForMe{}{}
  void save(){
    //some code here, but i need data from ClassForMe
    int i = classForMe.getData();
    ...
  }
private:
  ClassForMe classForMe;
};

如果我不清楚解释我的问题并且有人在想“为什么要测试抛出错误的代码”。 此代码运行良好,但不适用于我的平台。对我来说,它会抛出错误,因此可以为此类编写测试,例如我模仿 classForMe 的构造很好并且包含一些价值? 然后这个值会被用于void save()方法的测试?

#include <gtest/gtest.h>
#include "C.hpp"
class C_test  : public ::testing::Test
{
 ... ?? 
};

【问题讨论】:

  • 伪造测试有什么意义?如果您不在乎,您就不能不运行测试或删除它吗?
  • 我同意 molbnilo。如果该测试不打算通过,那么您不应该运行它。如果它不在您的平台上运行,而是在其他人上运行,那么您应该在您的平台上编译时有条件地删除该测试。
  • 重点是测试方法save()。但在我的情况下,我在测试环境中没有组件,这是构建 classForMe 所必需的,没有错误。所以我想用不是来自 ClasseForMe 的值来测试它。因为我知道这个 ClassForMe 在适当的环境中会构造得很好,但是当我得到这个组件以无错误地破坏 ClassForMe 时,我必须检查我的 C 类中的方法保存是否正常工作。
  • 那么合适的做法就是重构。

标签: c++ unit-testing googletest


【解决方案1】:

为了测试您的类C,我将使用hi-perf dependency injection 模拟ClassForMe(或者如果您可以使用所有纯虚拟方法创建抽象ClassForMe 接口类,则使用常规依赖注入)。通过这种方式,您可以在测试中为 ClassForMe 类设置期望 - 例如调用savegetData 的不同返回值。

struct ClassForMe{
    int getData() const;
};

template<class IMPL = ClassForMe>
class C
{
public:
  C(IMPL& impl):classForMe{impl}{}
  void save(){
    //some code here, but i need data from ClassForMe
    int i = classForMe.getData();

    std::cout << "i is " << i;
    //...
  }
private:
  IMPL& classForMe;
};

struct ClassForMeMock {
    MOCK_METHOD0(getData, int());
};

class C_test  : public ::testing::Test
{
    public:
    ClassForMeMock mock{};
    C<ClassForMeMock> c{mock};
};

TEST_F(C_test, SomeTest) {
    EXPECT_CALL(mock, getData()).WillOnce(testing::Return(42));

    c.save(); // will print "i is 42" to stdout
}

【讨论】:

  • 我做到了,就像你描述的那样。但是在带有测试的文件中,我收到了关于未定义对该模拟对象的引用的错误。 '对 C::save()' 的未定义引用和'对 C::C(ClassForMeMock &) 的未定义引用' 我在我的 cpp 文件中将构造函数和方法定义为:template `C ::C(T& t):classForMe{t}{} 模板 void C::save(){ //... } /... 模板类 C; ` 我想我需要在这里添加更多内容?
  • 如果您要切换到基于模板的方法,我认为您不能在 cpp 中定义 save - 除非您预先知道类型,否则您可以在 cpp 文件中定义模板,见stackoverflow.com/questions/115703/…。否则,class C 只能在标题中。
猜你喜欢
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
相关资源
最近更新 更多