I am learning mocking and using googletest I created MockServer class that should mock the abstract class IServer:
class IServer
{
virtual void writeData(QString buffer) = 0;
virtual QByteArray readData() = 0;
protected:
virtual ~IServer() = default;
};
class MockServer: public:: testing:: Test, public IServer
{
MOCK_METHOD(void, writeData, (QString buffer), (override));
MOCK_METHOD(QByteArray, readData, (), (override));
};
And now want to test the other class that uses it, however, I cannot initialize MockServer because it is an abstract class. How to solve this?
TEST_F(Serv_test, start)
{
?? MockServer mockServer; // <- how to declare it?
EXPECT_CALL(mockServer, writeData(testing::_)).Times(1);
EXPECT_CALL(mockServer, readData()).Return("testing");
Car car (nullptr, mockServer);
}
You are confusing a few things:
You are using a test fixture, but a test fixture needs to be a standalone class. You are mixing it with your mock class. You need to create a separate class for it.
The Car class should take a parameter of type mock class (not the test fixture).
.Return should be used inside WillOnce or WillRepeatedly among other places. You can't use it directly on EXPECT_CALL.
I rewrote your code as follows:
class IServer
{
public:
virtual void writeData(QString buffer) = 0;
virtual QByteArray readData() = 0;
protected:
virtual ~IServer() = default;
};
// Test fixture
class Serv_test : public ::testing::Test {
};
// Mock class
class MockServer: public IServer
{
public:
MOCK_METHOD(void, writeData, (QString buffer), (override));
MOCK_METHOD(QByteArray, readData, (), (override));
};
class Car{
public:
Car(int*, IServer* server):_server(server){
_server->writeData("testing");
_server->readData();
}
IServer* _server;
};
TEST_F(Serv_test, start)
{
MockServer mockServer; // <- how to declare it?
EXPECT_CALL(mockServer, writeData(testing::_)).Times(1);
EXPECT_CALL(mockServer, readData())
.WillOnce(testing::Return("testing"));
Car car (nullptr, &mockServer);
}
Working example here: https://godbolt.org/z/avsKdh37r
Related
I have implemented a Dependency Injection pattern in my code. I did that to be able to mock a service using gmock. The DI implementation works in production code, however, I am having trouble with my test setup. When using the EXPECT_CALL macro, I get "expression must have class type" error. I believe this is related to the way I designed the dependency, but I can't find an alternative solution (lack of experience). I have browsed previous threads on similar issues, but none helped. Would you be kind to take a look at the code below and hint possible workarounds (simplified code example using a Car-Engine interface)?
// 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();
}
I would like to be able to mock the engine implementation and instead of using a "real V8Engine", utilize the mock. Here is how I set up my test:
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 expects mock object as first parameter, you pass reference to mock.
either use *mockEngine:
TEST(TestCarClass, TestCarWithMockEngine)
{
IEngine *mockEngine = new MockEngine;
Car carUnderTest(mockEngine);
EXPECT_CALL(*mockEngine, start());
carUnderTest.Drive();
}
or avoid allocation directly:
TEST(TestCarClass, TestCarWithMockEngine)
{
MockEngine mockEngine;
Car carUnderTest(&mockEngine);
EXPECT_CALL(mockEngine, start());
carUnderTest.Drive();
}
I'm trying to mock a static function member with gmock. I found a section on the gMock Cookbook that talks about Mocking Free Functions. However it is not clear to me..
For instance, I have a static function called isActiveMode that I want to mock. Instead of calling isActiveMode directly, I have to introduce an interface for it and have a concrete subclass that calls the static function:
class MyClassInterface {
public:
...
virtual bool isActive() = 0;
};
class MyClass: public MyClassInterface {
public:
...
virtual bool isActive()
{
return isActiveMode();
}
};
Then I define the mock class:
class MyMock {
public:
MOCK_METHOD(bool, isActive, (), (override));
};
But this does not seem to work..
Does somebody have a clue on how to make this work?
Your mock class should be derived from the interface class.
class MyMock : public MyClassInterface {
public:
MOCK_METHOD(bool, isActive, (), (override));
};
If that doesn't help, please provide a minimum reproducible example showing how you are using the mock.
I got a class Car which uses speedInterface (it has a reference on it).
Now I want to mock speedInterface with Mock_SpeedInterface.
class speedInterface
{
public:
virtual ~speedInterface() {}
virtual int GetSpeed(void) = 0;
};
class Mock_SpeedInterface : public speedInterface
{
public:
MOCK_CONST_METHOD0(GetSpeed, int());
};
class Car
{
public:
Car(speedInterface& s) : Speedo(s) {}
virtual ~Car() {}
speedInterface& Speedo;
...
};
TEST(TestCar, Test1) {
Mock_SpeedInterface mockSpeed;
...
}
Trying to create mockSpeed leads to the following compiler error:
Error C2259 'Mock_SpeedInterface': cannot instantiate abstract class
IMHO class Mock_SpeedInterface is not an abstract class because it "implements" GetSpeed.
Why do I get this error and how do I prevent it?
Seems MOCK_CONST_METHOD0(GetSpeed, int()); is wrong. To have an ordinary answer I will quote the comment of the OP:
Changing it to MOCK_METHOD0 fix it.
I need to use polymorphism to do_something on objects inherited from BaseA but my D objects should have two seperated members named enabled. I mean that D::changeEnabled() should change SecondBaseB::BaseA::enabled = 0 and SecondBaseC::BaseA::enabled = 0 and these two members should be separate (different). Is it possible to have polymorphism and not using virtual inheritance? Without virtual public BaseA i have ambigous error. But with virtual inheritance i have only one BaseA::enabled.
//
// main.cpp
//
#include <iostream>
#include "D.h";
void do_something(BaseA& o) {
o.changeEnabled();
}
int main() {
SecondBaseB b;
SecondBaseC c;
D d;
do_something(b);
do_something(c);
do_something(d);
std::cout « "Hello, World!" « std::endl;
return 0;
}
//
// BaseA.h
//
class BaseA {
protected:
bool enabled;
public:
BaseA();
virtual void changeEnabled() = 0;
};
//
// BaseA.cpp
//
#include "BaseA.h"
BaseA::BaseA() : enabled(true) {
}
//
// SecondBaseB.h
//
class SecondBaseB : virtual public BaseA{
public:
virtual void changeEnabled();
};
//
// SecondBaseB.cpp
//
#include "SecondBaseB.h"
void SecondBaseB::changeEnabled() {
enabled = !enabled;
}
//
// SecondBaseC.h
//
#include "BaseA.h"
class SecondBaseC : virtual public BaseA {
public:
virtual void changeEnabled();
};
//
// SecondBaseC.cpp
//
#include "SecondBaseC.h"
void SecondBaseC::changeEnabled() {
enabled = !enabled;
}
//
// D.h
//
#include "SecondBaseB.h"
#include "SecondBaseC.h"
class D : public SecondBaseB, public SecondBaseC{
public:
virtual void changeEnabled();
};
In a different words. I have following scenario: base abstract class Car with engine member. I create DieselCar and ElectricCar which are inherited from Car. Then i want to create HybridCar which would inherited from DieselCar and ElectricCar and have two different engines. With using virtual inheritance there's only one engine. Without using virtual I cannot accomplish following:
void testDrive(Car* c) {
c->drive();
c->drive();
}
HybridCar h;
ElectricCar e;
testDrive(&h);
testDrive(&e)
Talking about your Car scenario, to have multiple information about Car subclass that have more than an Engine the code can be refactored using Composite Pattern, in this way:
Car owns an Engine
Engine is an interface or abstract class that acts like the Component
Leaf is a concrete subclass of Engine that has a meaning like ElectricEngine, DieselEngine, etc...
PowerUnit acts like the Composite and so, it owns references to some Engines
Then every costructor of every concrete subclass of Car initialize the attribute
Engine* engine;
declared in the abstract class Car, in correct way.
For example,
ElectricCar(){
//other members
engine=new ElectricEngine();
}
DieselCar(){
//other members
engine=new DieselCar();
}
HybridCar(){
//hybrid car is composed by an electric and diesel engine
engine=new PowerUnit(Engine* engines);
}
If the abstract class looks like
class Engine{
private bool enabled;
public:
virtual Engine* getEngine(int number=0){ return this};
virtual final bool isEnabled(){return this->enabled};
virtual final void setEnabled(bool value){ this->enabled=value;}
}
the getEngine() method must be implemented in his true function in subclass PowerUnit.
class PowerUnit{
private:
Engine*[] engines;
public:
PowerUnit(){
engines[0]=new ElectricCar();
engines[1]=new DieselCar();
}
getEngine(int number){ return engines[number];}
}
Finally, if the client (Car) wants to check in an hybrid car which engine is active(or both), it can use the pointer engine as in the following way that check if the first engine is active:
engine->getEngines(0)->isEnabled;
I have a class that is subclass of an external class over which I don't have any control. The external class depend on system resources. For example
class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
int doSomePrivateThing(int );
public:
virtual int DoSomething(int );
virtual ~MyClass();
}
int MyClass::doSomePrivateThing(int )
{
// do some private task
}
int MyClass::DoSomething(int n)
{
// Do MyClass Specific task
int k = doSomePrivateThing(n);
return ExternalBase::DoSomething(k); // This function depends on external system resources.
// Probably try to communicate with remote server
// or attempt access Storage or Display device etc.
}
MyClass::~MyClass()
{}
How can I break the dependency of MyClass and write unit test for MyClass::DoSomething(). Using composition in place of inheritance is not a choice as framework requires classes to be derived from this base class.
I am using C++ and GoogleTest/Mock. But any generalized solution is appreciated.
Thanks in advance.
There are two ways. I call them "a little more correct" way and "very ugly" way.
The "more correct" way:
Enclose external class functions with some additional layer than can be partial mocked.
class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
int doSomePrivateThing(int );
public:
virtual void BaseDoSomething(int) { return ExternalBase::DoSomething(v); }
virtual int DoSomething(int v);
virtual ~MyClass();
};
int MyClass::DoSomething(int n)
{
// Do MyClass Specific task
int k = doSomePrivateThing(n);
return BaseDoSomething(k);
}
And partial mock in UT in this way:
class TestableMyClass : public MyClass
{
public:
using MyClass::MyClass;
MOCK_METHOD1(BaseDoSomething, int(int));
};
TEST(A,A)
{
TestableMyClass objectUnderTest;
EXPECT_CALL(objectUnderTest, BaseDoSomething(112));
objectUnderTest.DoSomething(112);
}
When you need to call also the true base class method in your test - use WillOnce(Invoke...) with EXPECT_CALL.
The "very ugly" way:
Provide your own UnitTest implementation of ExternalBase and link it to your test. This "UnitTest" impolementation of ExternalBase should be based on some global Mocks objects.
ExternalBaseMock.hpp:
class ExternalBaseMock
{
public:
MOCK_METHOD1(DoSomething, int(int));
};
extern ExternalBaseMock externalBaseMock;
ExternalBaseMock.cpp:
ExternalBaseMock externalBaseMock;
int ExternalBase::DoSomething(int n)
{
return externalBaseMock.DoSomething(n);
}
Then your tests:
#include "ExternalBaseMock.hpp"
TEST(A,A)
{
MyClass objectUnderTest;
EXPECT_CALL(externalBaseMock, DoSomething(112));
objectUnderTest.DoSomething(112);
}