我正在尝试使用Google Mock测试抽象类。在forDummies指南之后,我构建了一个模拟我的课程:
AbstractFoo.h
class AbstractFoo {
public:
virtual void setSize(int w, int h) = 0;
void setSize(const QSize& s); // implemented as calling above function
}
MockFoo.h
#include "gmock/gmock.h"
class MockFoo : public AbstractFoo {
public:
MOCK_METHOD2(setSize, void(int w, int h));
}
FooTest.cpp
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "MockFoo.h"
TEST(AbstractFoo, MethodSetSize) {
MockFoo foo;
EXPECT_CALL(foo, setSize(5, 5)).Times(1);
foo.setSize(QSize(5, 5)); // this line produces compiler error
}
标记的行会产生以下编译器错误:
C2660:'MockFoo :: setSize':函数不带1个参数
我的理解是,由于MockFoo
扩展AbstractFoo
,它应该继承setSize(QSize)
方法。但是,情况似乎并非如此。我该如何解决这个问题?
答案 0 :(得分:2)
模拟类中方法的签名是错误的:
MOCK_METHOD2(setSize, bool(int w, int h));
并且基类具有带此签名的方法:
virtual void setSize(int w, int h) = 0;
我不确定您使用的是哪种编译器,但这应该是编译器错误。
修复签名,错误应该消失:
MOCK_METHOD2(setSize, void(int w, int h));
此外,
class MockFoo : AbstractFoo
应该是
class MockFoo : public AbstractFoo
您的问题与googlemock库无关 - 而是与c ++无关。由于[class.virtual] / 1,您无法实现的目标。
下一个示例演示了同样的问题:
struct A
{
A(int h,int l):x(h),y(l){}
int x; int y;
};
class AbstractFoo {
public:
virtual void setSize(int w, int h) = 0;
void setSize(const A& s){setSize(s.x,s.y);}
};
class MockFoo : public AbstractFoo
{
public:
void setSize(int , int ){}
};
int main()
{
MockFoo f;
A a(5,5);
f.setSize( a );
}
您可以通过重命名setSize(const QSize& s)
方法或将MockFoo
对象转换为AbstractFoo&
然后调用此方法来解决此问题。
您还可以查看NVI,因为它看起来就像您要做的那样。
答案 1 :(得分:1)
如果你正在搞乱彼此重载版本的成员方法,那么你可能会遇到gmock的问题。 Google模拟将每个模拟函数声明为单独的仿函数对象,当然您可以重载仿函数对象,您通常会在仿函数对象中重载单个operator()(...)方法。
我通常通过声明一个包装器模拟函数来解决这个问题,然后从我的重载函数中调用它。标题将如下所示:
<强> MockFoo.h 强>
#include "gmock/gmock.h"
class MockFoo : public AbstractFoo {
public:
void setSize(int w, int h) {
mocked_setSize(w, h); ///< workaround to call the mocked setSize instead.
}
MOCK_METHOD2(mocked_setSize, void(int w, int h));
}
现在,对setSize(w,h)
的每次通话都会定向到您的mocked_setSize(w,h)
方法。这意味着现在您必须在单元测试中执行以下操作:
<强> MockFoo.cpp 强>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "MockFoo.h"
TEST(AbstractFoo, MethodSetSize) {
MockFoo foo;
EXPECT_CALL(foo, mocked_setSize(5, 5)).Times(1);
foo.setSize(QSize(5, 5)); ///< now this should compile cleanly.
}
这样可以避免google mock在内部生成一个对象,其中包含您要声明的方法的名称。