1

我正在尝试使用 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 个参数

我的理解是,由于MockFooextends AbstractFoo,它应该继承该setSize(QSize)方法。然而,情况似乎并非如此。我怎样才能解决这个问题?

针对代码不准确进行了编辑

4

2 回答 2

3

如果您在使用彼此重载版本的成员方法,那么您可能会遇到 gmock 问题。Google mock 将每个模拟函数声明为单独的仿函数对象,虽然您当然可以重载仿函数对象,但您通常会做的是重载仿函数对象中的各个 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 内部会生成一个具有您尝试声明的方法名称的对象。

于 2014-06-20T11:11:24.000 回答
1

模拟类中方法的签名是错误的:

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,因为它看起来像您正在尝试做的事情。

于 2013-07-09T06:02:40.457 回答