3

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.

Nikolai
  • 359
  • 2
  • 10
  • It's a bit unclear, what you want to test actually. Do you want to ensure that a number of calls to `trigger()` is made from the `Spectrometer` class? – user0042 Nov 22 '17 at 21:31

1 Answers1

2

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;
}
user0042
  • 7,917
  • 3
  • 24
  • 39
  • Thank you for giving the full solution as an example. I wanted to avoid passing in the FlashLamp, because in the real system there are many more components so I did not think in this direction. However your solution is so good, that I think I just need to create a compound object with all the components and pass this in. – Nikolai Nov 23 '17 at 06:45