使用依赖注入并用 gmock 模拟它
Using dependency injection and mocking it with gmock
我在我的代码中实现了依赖注入模式。我这样做是为了能够使用 gmock 模拟服务。 DI 实现在生产代码中有效,但是,我在测试设置方面遇到了问题。使用 EXPECT_CALL 宏时,出现“表达式必须具有 class 类型”错误。我相信这与我设计依赖项的方式有关,但我找不到替代解决方案(缺乏经验)。我浏览过以前关于类似问题的主题,但 none 有所帮助。您能否看看下面的代码并提示可能的解决方法(使用 Car-Engine 接口的简化代码示例)?
// Engine interface class with pure virtual functions
class IEngine
{
public:
virtual ~IEngine() = default;
virtual void start() = 0;
virtual void stop() = 0;
};
// A V8Engine class implementing this interface
class V8Engine : public IEngine
{
public:
void start() override { std::cout << "V8 Engine started\n"; };
void stop() override { std::cout << "V8 Engine stopped\n"; };
};
// Car.h file
class Car
{
public:
Car(IEngine *engineService);
void Drive();
private:
IEngine* mEngine = nullptr;
};
// Car.cpp file
Car::Car(IEngine* engineService)
: mEngine(engineService)
{
if (mEngine == nullptr)
{
throw std::invalid_argument("service must not be null");
}
}
void Car::Drive()
{
mEngine->start();
mEngine->stop();
}
我希望能够模拟引擎实现,而不是使用“真正的 V8Engine”,而是利用模拟。以下是我设置测试的方式:
class MockEngine : public IEngine
{
public:
MOCK_METHOD(void, start, (), (override));
MOCK_METHOD(void, stop, (), (override));
};
TEST(TestCarClass, TestCarWithMockEngine)
{
IEngine *mockEngine = new MockEngine;
Car carUnderTest(mockEngine);
carUnderTest.Drive();
EXPECT_CALL(mockEngine, start()); // This is the part where I get the error due to invalid mockEngine setup
}
EXPECT_CALL
期望 mock 对象作为第一个参数,您将引用传递给 mock。
要么使用 *mockPtr
:
TEST(TestCarClass, TestCarWithMockEngine)
{
IEngine *mockEngine = new MockEngine;
Car carUnderTest(mockEngine);
EXPECT_CALL(*mockEngine, start());
carUnderTest.Drive();
}
或者直接避免分配:
TEST(TestCarClass, TestCarWithMockEngine)
{
MockEngine mockEngine;
Car carUnderTest(&mockEngine);
EXPECT_CALL(mockEngine, start());
carUnderTest.Drive();
}
我在我的代码中实现了依赖注入模式。我这样做是为了能够使用 gmock 模拟服务。 DI 实现在生产代码中有效,但是,我在测试设置方面遇到了问题。使用 EXPECT_CALL 宏时,出现“表达式必须具有 class 类型”错误。我相信这与我设计依赖项的方式有关,但我找不到替代解决方案(缺乏经验)。我浏览过以前关于类似问题的主题,但 none 有所帮助。您能否看看下面的代码并提示可能的解决方法(使用 Car-Engine 接口的简化代码示例)?
// Engine interface class with pure virtual functions
class IEngine
{
public:
virtual ~IEngine() = default;
virtual void start() = 0;
virtual void stop() = 0;
};
// A V8Engine class implementing this interface
class V8Engine : public IEngine
{
public:
void start() override { std::cout << "V8 Engine started\n"; };
void stop() override { std::cout << "V8 Engine stopped\n"; };
};
// Car.h file
class Car
{
public:
Car(IEngine *engineService);
void Drive();
private:
IEngine* mEngine = nullptr;
};
// Car.cpp file
Car::Car(IEngine* engineService)
: mEngine(engineService)
{
if (mEngine == nullptr)
{
throw std::invalid_argument("service must not be null");
}
}
void Car::Drive()
{
mEngine->start();
mEngine->stop();
}
我希望能够模拟引擎实现,而不是使用“真正的 V8Engine”,而是利用模拟。以下是我设置测试的方式:
class MockEngine : public IEngine
{
public:
MOCK_METHOD(void, start, (), (override));
MOCK_METHOD(void, stop, (), (override));
};
TEST(TestCarClass, TestCarWithMockEngine)
{
IEngine *mockEngine = new MockEngine;
Car carUnderTest(mockEngine);
carUnderTest.Drive();
EXPECT_CALL(mockEngine, start()); // This is the part where I get the error due to invalid mockEngine setup
}
EXPECT_CALL
期望 mock 对象作为第一个参数,您将引用传递给 mock。
要么使用 *mockPtr
:
TEST(TestCarClass, TestCarWithMockEngine)
{
IEngine *mockEngine = new MockEngine;
Car carUnderTest(mockEngine);
EXPECT_CALL(*mockEngine, start());
carUnderTest.Drive();
}
或者直接避免分配:
TEST(TestCarClass, TestCarWithMockEngine)
{
MockEngine mockEngine;
Car carUnderTest(&mockEngine);
EXPECT_CALL(mockEngine, start());
carUnderTest.Drive();
}