如何在 C++ 中使用 GMock 将方法(非虚拟)模拟为 Return 特定值?
How to Mock A Method(non-virtual) To Return Particular Value Using GMock in C++?
我的问题是我想将 Static Non-Virtual 方法模拟为 return true,最终 return假的。
我有静态方法
例如:
class SomeClass{
public:
static bool SomeClass::DoAction() {
// do some Actions
};
};
我想 return 在模拟期间始终为真,但默认情况下 return 为假,
反正有 Mock
我尝试了以下方法来检查 on-call 值并找出它导致错误的原因。
class MockSomeClass : public SomeClass {
public:
MockSomeClass() {
ON_CALL(this, DoAction).WillByDefault(testing::Return(true));
}
virtual ~MockSomeClass(){};
MOCK_METHODO(DoAction, bool());
由于Mock是用来离开函数的,有什么方法可以return函数的特定值,或者将return值替换为true并继续使用gmock进行测试和 C++ 中的 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
使用默认值
using ::testing::DefaultValue;
DefaultValue<bool>::Set(true);
// call the mock methods
DefaultValue<bool>::Clear();
使用 Invoke,这不起作用,因为静态方法是非空的。
除了上述方法还有其他解决方法吗
本来想写个评论,但是太长了,所以这里是答案。如果您根本无法更改生产代码,请不要进一步阅读,根本不可能对其进行测试(至少不可能更改对 SomeClass::DoAction()
的调用行为)。如果您可以稍微更改代码,并且希望使其更具可测试性和灵活性,请定义负责调用静态(或全局)函数的接口并将其传递给系统的构造函数。
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(); }
但我不喜欢也不推荐这种解决方案。
我的问题是我想将 Static Non-Virtual 方法模拟为 return true,最终 return假的。
我有静态方法 例如:
class SomeClass{
public:
static bool SomeClass::DoAction() {
// do some Actions
};
};
我想 return 在模拟期间始终为真,但默认情况下 return 为假, 反正有 Mock
我尝试了以下方法来检查 on-call 值并找出它导致错误的原因。
class MockSomeClass : public SomeClass {
public:
MockSomeClass() {
ON_CALL(this, DoAction).WillByDefault(testing::Return(true));
}
virtual ~MockSomeClass(){};
MOCK_METHODO(DoAction, bool());
由于Mock是用来离开函数的,有什么方法可以return函数的特定值,或者将return值替换为true并继续使用gmock进行测试和 C++ 中的 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
使用默认值
using ::testing::DefaultValue; DefaultValue<bool>::Set(true); // call the mock methods DefaultValue<bool>::Clear();
使用 Invoke,这不起作用,因为静态方法是非空的。
除了上述方法还有其他解决方法吗
本来想写个评论,但是太长了,所以这里是答案。如果您根本无法更改生产代码,请不要进一步阅读,根本不可能对其进行测试(至少不可能更改对 SomeClass::DoAction()
的调用行为)。如果您可以稍微更改代码,并且希望使其更具可测试性和灵活性,请定义负责调用静态(或全局)函数的接口并将其传递给系统的构造函数。
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(); }
但我不喜欢也不推荐这种解决方案。