gpt4 book ai didi

c++ - 如何在 C++ 中使用 GMock 模拟方法(非虚拟)以返回特定值?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:59:18 26 4
gpt4 key购买 nike

我的问题是我想模拟一个 Static Non-Virtual 方法来返回 true,最终返回 false。

我有静态方法例如:

class SomeClass{ 
public:
static bool SomeClass::DoAction() {
// do some Actions
};
};

我想在模拟期间始终返回 true,但默认情况下返回 false,反正有模拟

我尝试了以下方法来检查 on call 值并发现它导致 false。

class MockSomeClass : public SomeClass {
public:
MockSomeClass() {
ON_CALL(this, DoAction).WillByDefault(testing::Return(true));
}
virtual ~MockSomeClass(){};
MOCK_METHODO(DoAction, bool());

由于Mock是用来离开函数的,有什么方法可以让函数返回一个特定的值,或者将返回值替换为true,继续在C++中使用gmock和gtest进行测试运行。考虑下面的例子例如:

  FunctionA(){
if (SomeClass::DoAction()){
// do Actions - I wanted to pass the call do the actions.
}
};

这里我想测试 if true 情况下的操作,是否有任何方法可以在不更改任何底层代码的情况下测试上述方法。

我已经尝试了该方法中存在的不同方法,但我仍然无法获得确切的解决方案。 https://github.com/google/googletest/tree/master/googlemock/docs

  1. 使用默认值

    using ::testing::DefaultValue;
    DefaultValue<bool>::Set(true);
    // call the mock methods
    DefaultValue<bool>::Clear();
  2. 使用 Invoke,这不起作用,因为静态方法是非 void 的。

除上述方法外,还有其他解决方法吗?

最佳答案

我只想写评论,但太长了,所以这里是答案。如果您根本无法更改您的生产代码,请不要进一步阅读,根本不可能对其进行测试(至少不可能改变调用 SomeClass::DoAction() 的行为) .如果您可以稍微更改代码,并且希望使其更具可测试性和灵 active ,请定义负责调用静态(或全局)函数的接口(interface)并将其传递给系统的构造函数。

class SomeClass{ 
public:
static bool DoAction() {
std::cout << "Call to SomeClass::DoAction" << std::endl;
return false;
};
};

// you absolutely need this, otherwise your code will be strongly dependent on the real SomeClass implementation
class ISomeClassInterface {
public:
virtual ~ISomeClassInterface() = default;
virtual bool DoAction() = 0;
};

/*
* use it in the production
* you can even make it a default constructor parameter to simplify objects
* constructions outside testing env
*/
class RealSomeClassInterface: public ISomeClassInterface {
public:
~RealSomeClassInterface() override = default;
bool DoAction() override {
// call to real SomeClass
return SomeClass::DoAction();
}
};

class MockSomeClassInterface: public ISomeClassInterface {
public:
~MockSomeClassInterface() override = default;
MOCK_METHOD0(DoAction, bool());
};

class System {
public:
System(std::shared_ptr<ISomeClassInterface> interface): interface_(interface) {}
// let's imagine this is your code that is dependent on the DoAction return value
bool DoAction() {
return interface_->DoAction();
}
private:
std::shared_ptr<ISomeClassInterface> interface_;
};

TEST(xxx, yyy) {
auto realInterface = std::make_shared<RealSomeClassInterface>();
auto mockInterface = std::make_shared<MockSomeClassInterface>();
ON_CALL(*mockInterface, DoAction()).WillByDefault(Return(true));
System systemWithRealInterface(realInterface);
System systemWithMockInterface(mockInterface);
std::cout << "System::DoAction returns: " << systemWithRealInterface.DoAction() << std::endl;
std::cout << "System::DoAction returns: " << systemWithMockInterface.DoAction() << std::endl;
}

测试输出应该是这样的:

[ RUN      ] xxx.yyy
Call to SomeClass::DoAction
System::DoAction returns: 0

GMOCK WARNING:
Uninteresting mock function call - taking default action specified at:
whatever.cpp:76:
Function call: DoAction()
Returns: true
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#knowing-when-to-expect for details.

System::DoAction returns: 1
[ OK ] xxx.yyy (0 ms)

您也可以使用 C++ 模板进行破解

    template <class T>
bool DoAction() { return T::DoAction(); }

但我不喜欢也不推荐这种解决方案。

关于c++ - 如何在 C++ 中使用 GMock 模拟方法(非虚拟)以返回特定值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51388755/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com