【问题标题】:How to access a private member in Google Mock如何访问 Google Mock 中的私人成员
【发布时间】:2015-08-03 22:47:00
【问题描述】:

我正在尝试为具有私有向量的类编写一个模拟,它将数据插入到私有向量中。但是,我没有看到使用 Google Mock 的方法。理想情况下,我不想在我的界面中包含任何与测试相关的内容。另外,我不想让私有向量受保护并子类化该类并添加访问器方法,因为这会导致我的代码泄漏其实现。

这是我目前所拥有的。我想要完成的是使用 Fake 类插入数据,并使用 Mock 类在指向 Fake 类的指针上调用 Real::first() (这样我就可以使用 Fake 的向量而不是 Real 的)。编译此程序时,返回 -1 而不是 4。

#include <iostream>
#include <vector>
#include <gmock/gmock.h>

using namespace std;
//using ::testing::_;
using ::testing::Invoke;

class A {
protected:
    vector<int> a;

public:
    virtual int first() = 0;
    virtual ~A() {}
};

class Real : public A {
public:
    virtual int first() {
        cout << "size: " << a.size() << endl;
        return a[0];
    }
};

class Fake : public A {
public:
    virtual void insert(int b) {
        a.push_back(b);
        cout << a.size() << endl;
    }

private:
    virtual int first() { return -1; }
};

class Mock : public A {
public:
    Mock(Fake* c) :
        c_(c) {}

    MOCK_METHOD0(first, int());

    void delegate() {
        ON_CALL(*this, first())
            .WillByDefault(Invoke((Real*)c_, &Real::first));
    }

private:
    Fake* c_;
};

int main(void) {
    Fake c;
    c.insert(4);

    Mock z(&c);

    z.delegate();

    cout << z.first() << endl;
    return 0;
}

有谁知道我做错了什么?还是有更简单的方法来实现这一点?

【问题讨论】:

    标签: c++ unit-testing mocking googlemock


    【解决方案1】:

    赋予Mock 的实现实例c 是一个Fake 对象,再多的指向它的指针转换都不会使它成为Real。因为FakeReal 都从A 派生first(),所以即使编译器认为它调用了Realfirst() 函数,Fake 对象的first() 也会成功调用。

    要说出你想要什么并不容易,因为你的例子太小了(在这种最小的情况下,模拟并不是真正必要的),但是有多种方法可以实现你想要的行为,一些在我的脑海中浮现:

    选项 1

    A 中提供first 的默认定义并从Fake 中删除该定义:

    class A {
    protected:
        vector<int> a;
    
    public:
        virtual int first() {
            return a[0];
        }
    
        virtual ~A() {}
    };
    
    class Fake : public A {
    public:
        virtual void insert(int b) {
            a.push_back(b);
            cout << a.size() << endl;
        }
    };
    

    选项 2

    firstFake 中的工作定义。我知道,我知道,这段代码不属于Fake,但是对于这种琐碎的情况,它是一个快速修复。

    class Fake : public A {
    public:
        virtual void insert(int b) {
            a.push_back(b);
            cout << a.size() << endl;
        }
    
    private:
        virtual int first() {
            return a[0];
        }
    };
    

    选项 3

    如果所有这些都是关于不调用Afirst() 中的打印输出,我建议您改为模拟输出流。

    【讨论】:

    • 我考虑了选项 1,但将向量保留为受保护的 soley 以进行测试似乎有点奇怪。任何想要继承 A 的“真实”类都不需要直接访问向量。我认为你的第一段很好地解释了这里打破封装的问题:无论如何我都需要某种技巧来使其可测试。
    【解决方案2】:

    这稍微打破了第一个要求,但是为使测试工作而添加的样板数量很少。

    将存储从 A 和 mock 分离到它自己的类中,并将其注入构造函数中。

    class AStorage {
    vector<int> vals;
    };
    
    class A {
    AStorage& storage;
    
    public:
    A(AStorage& stor) :
    storage(stor) {}
    };
    

    很遗憾,A 不能拥有自己的存储空间。但是,测试现在更容易了,因为测试将引用存储对象,允许它在幕后更改数据。

    【讨论】:

      猜你喜欢
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2015-07-23
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多