如何使用 gmock 模拟修改 C++ 类中的私有变量的成员函数?
Posted
技术标签:
【中文标题】如何使用 gmock 模拟修改 C++ 类中的私有变量的成员函数?【英文标题】:How to mock member functions that modify private variables in a C++ class, using gmock? 【发布时间】:2019-11-18 15:32:07 【问题描述】:我正在努力解决使用 gmock 进行模拟的问题。下面的简化示例描述了它。我在一个类中有公共成员函数,既不返回任何值,也不接受任何输入。它们只更改类中的一些私有变量。还有第三种方法使用这两种方法的效果来计算一些东西(比如,p),然后再将结果吐出给外界。我需要知道如何正确模拟update_a()
和update_b()
。在某种程度上,我可以嘲笑他们。但我只是不知道如何将一些“动作”与其模拟版本相关联,以便通过调用它们我可以对私有变量产生一些影响。这是我目前所拥有的:
class MyClass
private:
int a,
int b,
int p;
public:
MyClass() : a, b, p
void update_a()
a += 2;
void update_b()
b += 5;
int calculate_p()
update_a();
update_b();
p = a * 100 + b * 50; // Just some random math making use of a and b.
return p;
class MockMyClass :public MyClass
public:
MOCK_METHOD(void, update_a, (), (override));
MOCK_METHOD(void, update_b, (), (override));
int deletegate_to_real()
return MyClass::calculate_p();
TEST(CalculatingP_Test, otherMemberFunctionsInvoked)
MockMyClass mockob;
EXPECT_CALL(mockOb, update_a()).Times(1);
EXPECT_CALL(mockOb, update_b()).Times(1);
mockOb.delegate_to_real();
测试通过,因为测试只检查是否调用了 update_a()
和 update_b()
的模拟版本。但是,我无法获得update_a()
和update_b()
的模拟版本来执行可以直接修改a
和b
的操作。将private
说明符更改为protected
是我能想到的一种方法。但这不会影响设计吗?
【问题讨论】:
friend
testing/mock classes 也是另一种选择。
你为什么需要它?您的被测单元调用了这些方法,是的!这就是测试类测试的重点。对MyClass
的测试以及update_a()
和update_b()
是否做预期的事情将单独编写(没有MockMyClass
)
@Yksisarvinen:是的,你说得有道理。在不使用 MockMyClass 的情况下,应该对 update_a() 和 update_b() 进行单独的测试。但是,我有一个计算_p() 的测试用例,它需要假设 a = 20000 和 b = 20000。我不允许向当前类引入任何新方法,如 set_a、set_b。我也不想运行循环,只是为了将 a 和 b 的值提高到那么高。所以,我需要一些嘲笑。
我将尝试使用受保护的而不是私有的,看看这是否符合我的意图。
【参考方案1】:
您可以通过 DIP 走得更远:
struct IVarAB
virtual ~IVarAB() = default;
virtual void update_a() = 0;
virtual void update_b() = 0;
virtual int get_a() = 0;
virtual int get_b() = 0;
;
class VarAB : public IVarAB
int a = 0;
int b = 0;
public:
void update_a() override a += 2;
void update_b() override b += 5;
int get_a() override return a;
int get_b() override return b;
;
class MyClass
private:
std::unique_ptr<IVarAB> varAB;
int p = 0;
public:
MyClass() : MyClass(std::make_unique<VarAB>())
explicit MyClass(std::unique_ptr<IVarAB> varAB) : varABstd::move(varAB)
void update_a() varAB->update_a();
void update_b() varAB->update_b();
int calculate_p()
update_a();
update_b();
p = varAB->get_a() * 100
+ varAB->get_b() * 50; // Just some random math making use of a and b.
return p;
;
然后您的模拟可以为a
和b
定义返回值。
【讨论】:
我了解您在此处放置的设计,但这需要我对当前设计进行重大更改,这是我不被允许的。【参考方案2】:决定我可以继续将“私人”替换为“受保护”。这解决了我所有的问题。
class MockMyClass :public MyClass
public:
MOCK_METHOD(void, update_a, (), (override));
MOCK_METHOD(void, update_b, (), (override));
void set_dummy_a(int arg_a) a = arg_a;
void set_dummy_b(int arg_b) b = arg_b;
int deletegate_to_real()
return MyClass::calculate_p();
TEST(CalculatingP_Test, otherMemberFunctionsInvoked)
MockMyClass mockob;
EXPECT_CALL(mockOb, update_a()).Times(1);
EXPECT_CALL(mockOb, update_b()).Times(1);
mockOb.delegate_to_real();
TEST(CalculatingP_Test, shouldCalculateP_basedon_a_and_b)
MockMyClass mockob;
EXPECT_CALL(mockob, update_a()).WillRepeatedly([&mockob]()
mockob.set_dummy_a(20000););
EXPECT_CALL(mockob, update_b()).WillRepeatedly([&mockob]()
mockob.set_dummy_b(20000););
int expected 3000000;
EXPECT_EQ(expected, mockob.delegate_to_real());
【讨论】:
以上是关于如何使用 gmock 模拟修改 C++ 类中的私有变量的成员函数?的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中的类中初始化与公共和私有相同的函数:它是如何工作的?