我正在测试一个有工厂的班级。该工厂是使用谷歌模拟嘲笑。我使用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()
相同的指针,但是我不知道如何实现。
答案 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
。既是工厂的返回类型,又是系统内部的工厂指针。