I have some C++ code similar to the example given below. I would like to write a unit test to verify that mFlashLamp.trigger is called exactly five times. However, up to now I was not able to figure out a good way to do this.
I have the following restraints: Compliance to Misra / GoogleTest / GoogleMock
include <iostream>
class FlashLamp
{
public:
virtual void trigger(){
std::cout << "Trigger FlashLamp" << std::endl;
}
};
class Spectrometer
{
public:
FlashLamp mFlashLamp;
void foo(){
for( int i=0; i<5; i++ ){
mFlashLamp.trigger();
}
}
};
int main(){
Spectrometer S;
S.foo();
return 0;
}
Does anybody have a good and clean solution for a unit test. One solution I can think of is to
class Spectrometer
{
public:
FlashLamp mFlashLamp;
FlashLamp* pFlashLamp;
}
have an additional pointer to the instance variable and use this to access the trigger. But this would mean some code bloat as it requires a null pointer check on every dereference. Does anybody have an idea for a better solution.
PS: I really tried to come up with a good title but couldn't. If someone has any improvements please feel free to edit it.
The idiomatic way in unit testing is to use interfaces and Mock Classes:
#include <iostream>
// The interface definition
struct IFlashLamp {
virtual ~IFlashLamp() {}
virtual void trigger() = 0;
};
class FlashLamp : public IFlashLamp
{
public:
virtual void trigger() override {
std::cout << "Trigger FlashLamp" << std::endl;
}
};
class Spectrometer
{
public:
IFlashLamp& mFlashLamp;
Spectrometer(IFlashlamp& flashLamp) : mFlashLamp(flashLamp) {}
void foo(){
for( int i=0; i<5; i++ ){
mFlashLamp.trigger();
}
}
};
You'll implement the interface with a mock class, that allows you to inspect the expectations regarding calls to the interface:
class FlashLampMock : public IFlashlamp {
int triggerCallCounter;
public:
FlashLampMock() : triggerCallCounter(0) {}
virtual void trigger() override {
++triggerCallCounter;
}
int getTriggerCallCounter() const { return triggerCallCounter; }
};
This is the unit test then:
int main(){
FlashLampMock flashLampMock;
Spectrometer S(FlashLampMock);
S.foo();
assert(flashLampMock.getTriggerCallCounter() == 5);
return 0;
}