如何在C++中模拟成员对象
How to Mock Member Objects in C++
我想为我们的项目创建一个单元测试环境。但是我不知道如何为班级成员创建模拟。我想用一个例子来解释我的问题。
在我的旧项目中,我们使用了一种模拟选择机制,在我看来这是非常丑陋的。这是老年人的方法:
class member {
};
class member_mock_1 {
};
class member_mock_2 {
};
class parent {
#if defined UNIT_TEST_1
typedef member_t member_mock_1;
#elif defined UNIT_TEST_2
typedef member_t member_mock_2;
#else
typedef member_t member;
#endif
private:
member_t mem;
};
第一个问题是用父类的typedefing来模拟成员对象的类是否是一种正确的方法?最佳实践是什么?如果我想使用单元测试框架,比如 gtest,我应该使用这种方式还是有另一种方法来嘲笑成员?
注1:如果虚拟机制被激活,可以创建基类来简化模拟,如果一个类是pod什么的,我不想使用这个机制。
注意2:我也觉得将成员类型作为模板参数传递很丑陋,一切都成为项目中的模板。我不想那样做。下面是一个示例:
template <typename M>
class parent {
private:
M mem;
};
#if defined UNIT_TEST_1
typedef parent_t parent<member_mock_1>;
#elif defined UNIT_TEST_2
typedef parent_t parent<member_mock_2>;
#else
typedef parent_t parent<member>;
#endif
这是我在这里建议的方法:
member_mock_1.hpp
class member_mock_1 {
};
member_mock_2.hpp
class member_mock_2 {
};
模拟.hpp
template <typename TYPE>
struct mock { using type = TYPE; };
#define ENABLE_MOCKING(NamE)
using NamE ## _t = mock<NamE>::type
member_mock.hpp
#if define UNIT_TEST_1
template<>
struct mock<member> { using type = member_mock_1 };
#endif
#if define UNIT_TEST_2
template<>
struct mock<member> { using type = member_mock_2 };
#endif
会员.hpp
class member {
};
ENABLE_MOCKING(member);
家长.hpp
class parent {
private:
member_t mem;
};
我上面提到的方法适用于普通类。我认为,对于模板类,应该做一些额外的工作。
因此,作为结论,我建议使用像上面这样的单元测试结构。可能没有必要,还有其他一些机制或方法可以满足该要求。也许我还在重新发明轮子:(
请建议一种你知道的嘲笑班级成员的方法。
谢谢。
是的,您正在重新发明轮子 代码看起来非常混乱:
#if defined UNIT_TEST_1
typedef parent_t parent<member_mock_1>;
#elif defined UNIT_TEST_2
typedef parent_t parent<member_mock_2>;
#else
typedef parent_t parent<member>;
#endif
有几种工具可用。我使用Typemock Isolator++,因为您可以模拟几乎所有内容,而无需触及您的生产。还有一件事,您在模拟上设置的行为将仅在测试范围内应用,因此每个测试都有一个单独且独立的设置。
您可以访问该成员,即使它是私有的:
member* mock_member = FAKE<member>;
parent* my_parent = new parent();
ISOLATOR_SET_MEMBER(my_parent, mem, mock_member);
并且很容易得到它:
member* get_member;
ISOLATOR_GET_MEMBER(my_parent, mem, get_member);
此外,它允许伪造抽象类、全局方法、纯虚拟方法、私有和受保护方法,为其设置行为。此外,访问隐藏的数据成员并调用它们。查看此内容以获取更多信息。
我的情况与您类似 - 将单元测试引入遗留C++项目。为此,我使用了很多预处理器指令以及Google Test和Google Mock。特别是,如果我面对你的例子,我会做如下:
#if defined UNIT_TEST
class imember
{
virtual void a_method() = 0;
};
#endif
class member
#if defined UNIT_TEST
: public imember
#endif
{
void a_method()
{
// do something
};
};
class parent {
public:
#if defined UNIT_TEST
parent(imember mem) : mem_(mem) {};
#endif
private:
#if defined UNIT_TEST
imember mem_;
#else
member mem_;
#endif
};
现在,使用Google Mock定义一个模拟类:
class mockmember : public imember
{
public:
MOCK_METHOD0(a_method, void());
};
模拟课现已准备就绪。使用 Google 测试定义您的测试方案:
class parenttest : public testing::Test
{
public:
parenttest() : member_(mockmember()), parent_(member_) {}
virtual void SetUp() {}
virtual void TearDown() {}
protected:
parent parent_;
mockmember member_;
};
TEST_F(parenttest, a_func)
{
EXPECT_CALL(member_, a_method());
int ret = parent_.a_func();
ASSERT_EQ(0, ret);
}
免责声明,我在Typemock工作。
山姆是完全正确的。此外,您不需要为每个单元测试创建 3 个不同的 member_mock 类。
您可以简单地设置行为,例如,为 member 中的某些私有方法设置行为:
member* mock_member = FAKE<member>;
PRIVATE_WHEN_CALLED(member, somePrivateMethod()).Return(0);
接下来使用 PRIVATE_WHEN_CALLED(mock_member, somePrivateMethod())
将重载 somePrivateMethod() 的行为,因此,与其创建大量不同的模拟类,只需根据需要更改行为即可。
希望对您有用!
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 在运行时有条件地删除类成员或跳过调用该成员对象的构造函数
- 模拟成员函数调用 lambda
- 在类 gtest/gmock 进行单元测试时模拟成员函数C++
- C++是否有定义的方法来传递指向类的成员对象的成员函数的指针
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- 声明成员对象而不调用其默认构造函数
- 指向成员对象的指针 - 中断线程
- 是否有更好的方法来封装成员对象可以访问的共享存储池?
- 应该在成员对象上调用析构函数
- 调用成员对象的构造函数
- 将 const 类型引用对象注册为类成员对象C++
- 修改类 c++ 中的成员对象
- 谷歌模拟:测试对象的某个属性
- 从成员对象调用方法
- 从对象调用成员对象,错误:引用非常量值的初始值必须是左值
- 构造函数,成员对象
- 不能使外部类成为内部类内的成员对象
- 使用从另一个类继承的类的对象初始化成员对象
- 如何在C++中模拟成员对象