如何拦截gmock动作的返回值

时间:2019-05-17 14:17:57

标签: c++ unit-testing googletest

我正在测试一个有工厂的班级。该工厂是使用谷歌模拟嘲笑。我使用action和WillByDefault()启用了模拟工厂来构造示例对象并返回指向它们的指针。在测试中,我要求类使用模拟的工厂创建对象,并将指针返回给创建的对象。我想确保从类返回的指针与模拟工厂返回给该类的指针相同。

让我们说我有一个班犬,一个狗工厂和一个使用该工厂的狗窝。

class dog;

class dogFactory{
    dog* makeDog() { return new dog; }
}

ACTION(makeDogInMock){ return new dog; }

class factoryMock : public factory{
    MOCK_METHOD1(makeDog, dog*());
}

class kennel{
    public:
    dog* dogInKennel;
    dogFactory factory;

    void putDogInKennel(){
        this->dogInKennel = factory.makeDog();
    }

    dog* getDogInKennel(){
        return this->dogInKennel;
    }

}

然后在测试构造函数中,我将该操作用作默认操作:

ON_CALL(factoryMock, dog(_)).WillByDefault(makeDogInMock)

在测试中,我想知道狗窝是否返回与在dogFactory中调用时返回的putDogInKennel()相同的指针,但是我不知道如何实现。

1 个答案:

答案 0 :(得分:0)

在您的示例中,它将永远不是您在默认操作中指定的狗,因为系统的设计不正确(当然,如果您想使用工厂模拟对其进行测试)。在系统(kennel中,您不应保留具体的工厂对象,而应保留指向工厂接口的指针。这称为依赖注入。您的示例可以通过以下方式进行修改:

class Dog{};

class IDogFactory {
public:
    virtual ~IDogFactory() = default;
    virtual Dog* makeDog() = 0;
};

class DogFactory: public IDogFactory {
public:
    ~DogFactory() override = default;
    Dog* makeDog() override {
        return new Dog;
    }
};

class DogFactoryMock: public IDogFactory {
public:
    MOCK_METHOD0(makeDog, Dog*());
};

class Kennel {
public:
    explicit Kennel(IDogFactory* factory): factory_(factory) {}
    void putDogInKennel(){
        dogInKennel_ = factory_->makeDog();
    }
    Dog* getDogInKennel(){
        return dogInKennel_;
    }
private:
    Dog* dogInKennel_;
    IDogFactory* factory_;
};

using testing::Return;

TEST(xxx, yyy) {
    Dog d;
    DogFactoryMock factoryMock;
    ON_CALL(factoryMock, makeDog()).WillByDefault(Return(&d));
    Kennel sut(&factoryMock);
    sut.putDogInKennel();
    Dog* dPtr = sut.getDogInKennel();
    std::cout << (dPtr == &d) << std::endl;  // outputs "true"
}

IDogFactory是能够创建Dog对象的工厂接口。 Dog创建过程的精确程度取决于工厂的实现,但是您的系统不依赖于工厂。因此,在生产环境中,您可以创建Kennel并将指针传递到DogFactory,而在测试中可以将指针传递到DogFactoryMock。在示例中,我使用了指向堆栈上对象的原始指针,但是我建议改用std::shared_ptr。既是工厂的返回类型,又是系统内部的工厂指针。