C++ 谷歌模拟非虚拟和私人功能
我试图为私有/非虚拟/静态函数编写mock,并找到了一种方法来实现同样的功能 下面是它的样子 假设我有一个C++ 谷歌模拟非虚拟和私人功能,c++,unit-testing,c++11,c++14,googlemock,C++,Unit Testing,C++11,C++14,Googlemock,我试图为私有/非虚拟/静态函数编写mock,并找到了一种方法来实现同样的功能 下面是它的样子 假设我有一个类a,需要在类UsingA中模拟和使用它。这两个类的定义如下所示 class A { friend class UsingA; int privateFn() {} public: int nonVirtual() {} }; // The UsingA class class UsingA { A &a1; public: UsingA(A
类a
,需要在类UsingA
中模拟和使用它。这两个类的定义如下所示
class A
{
friend class UsingA;
int privateFn() {}
public:
int nonVirtual() {}
};
// The UsingA class
class UsingA {
A &a1;
public:
UsingA(A & _a1) : a1(_a1) {}
int CallFn() {
return a1.nonVirtual();
}
int CallFn2() {
return a1.privateFn();
}
};
我知道mock用于生成类的行为,在创建mock时,我们需要从原始类派生
但是,为了模拟行为,我决定不从原始类派生,而是注释类A
,并生成一个同名的模拟类,即类A
。
下面是我的模拟课的样子
// Original class A is commented / header file removed
class A {
public:
MOCK_METHOD0(nonVirtual, int());
MOCK_METHOD0(privateFn, int());
};
我的测试通常是模拟测试
TEST(MyMockTest, NonVirtualTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, nonVirtual())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn();
EXPECT_EQ(retVal,100);
}
TEST(MyMockTest, PrivateTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, privateFn())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn2();
EXPECT_EQ(retVal,100);
}
一切正常,我可以通过这个模拟来测试UsingA
问题是
这看起来更简单,也能达到目的,但我在浏览谷歌模拟示例时还没有见过这种示例。如果我这样做会出什么问题吗
老实说,我没找到
注意:各位,我使用
friend
仅用于演示。我的实际用例完全不同。谢谢我们在一些测试项目中使用您的使用模拟类型来检查我们使用依赖注入传递的更大类上的回调。在我们的例子中,这些方法被声明为虚拟的
在你的情况下,他们不是。您的模拟实现将隐藏原始实现(如果有)。所以我认为这里没有问题。错误在于您没有测试真正的代码,因为:
- 评A班
- 生成具有相同名称的模拟类
long non-irtual
在模拟中-以前是int
nonVirtual()==0xFF'FFFF'FFFF
(大于INTMAX
)正在执行一些操作A
中进行更改-因此real使用A
具有经过测试但在real代码中永远无法访问的分支class A {
public:
MOCK_METHOD0(nonVirtual, long()); // change
MOCK_METHOD0(privateFn, int());
};
void UsingA::processA()
{
if (a.nonVirtual() > VERY_BIG_NUMBER)
{
throw runtime_error("oops");
}
}
TEST_F(UsingATest, throwOnVeryBigNumber)
{
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VERY_BIG_NUMBER + 1));
ASSERT_THROW(objectUndertTest.processA());
}
但是realA
没有改变-因此我们在UsingA类中测试不可访问的代码:
class A {
public:
int nonVirtual(); // not changed
...
};
最好的解决方案是(按顺序):
A
和UsingA
w/o任何存根-在一个测试用例中一起测试它们-因此您测试真实代码-这称为template <class T = A>
class UsingA {
T &a1;
public:
UsingA(T & _a1) : a1(_a1) {}
long CallFn() {
using ANonVirtualResult = std::invoke_result_t<&T::nonVirtual>;
static_assert(std::is_same<long, ANonVirtualResult>::value);
return a1.nonVirtual();
}
...
};
模板
类UsingA{
T&a1;
公众:
UsingA(T&_a1):a1(_a1){
long CallFn(){
使用anInvirtualResult=std::invoke\u result\t;
静态断言(std::is\u same::value);
返回a1.非虚拟();
}
...
};
在测试中:
class UsingATest : public ::testing::Test
{
protected:
StrictMock<AMock> aMock;
using ClassUnderTest = UsingA<AMock>;
ClassUnderTest objectUnderTest{aMock};
};
TEST_F(UsingATest, useNonVirtual)
{
const auto VALUE = 123456;
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VALUE));
ASSERT_EQ(VALUE, objectUnderTest.CallFn());
}
类UsingATest:public::testing::Test
{
受保护的:
StrictMock是模拟类的变通方法,没有虚拟函数。Hello..谢谢你的回答。根据我的经验,我们模拟类不是为了测试被模拟的类。我们模拟类是为了测试使用被模拟类的类。我不确定在这种情况下功能如何重要,因为无论如何,模拟都不会调用original除非明确调用,否则实现。我假设一个是mock类,UsingA是一个客户机?这里不是这样吗?您好,是这样的UsingA
正在使用moka
我理解您想说的关于我做错了什么,但我最初的问题的目的是检查这是否真的是个坏主意,因为我可以给我的MockA编写代码,以返回任何可能产生类似于您在回答中提到的情况的内容可能不是“非常糟糕”的想法,但我在回答中提到了“缺点”。简单地说,就是这样的“手册”在被测代码和单元测试代码之间替换类型可能是难以检测到的不兼容问题的根源,因为您的测试看不到真正的代码。您可能会在gmock文档中提到的模板技巧中看到