2

I am having difficulties in figuring out how to mock the singleton class, and test it in another class. The goal is to verify that a method from a singleton class (Alarm) gets called from another class (CEvnts).

I was able to test this successfully by eliminating the singleton function, but since it is legacy code, I cannot change the structure.

Going through several articles and posts online, I have not found a clear answer. Does anyone know how to set up the Google Test for a singleton class? Any references or articles can be a big help.

Singleton Class:

class Alarm
{
public:
    Alarm();
    virtual ~Alarm();

    // Singleton
    static Alarm* find(void)
    {
        if (!Alarm_Instance)
        {
            Alarm_Instance = new Alarm();
        }
        return Alarm_Instance;
    }

    // Member methods
    virtual ENUM_TYPE getType(ENUM_TYPE ENUM_ARG);

private:
    static Alarm* Alarm_Instance;
};

ENUM_TYPE Alarm::getType(ENUM_TYPE ENUM_ARG)
{
    return aMatch[ENUM_ARG].aType;
}

Mock:

class Alarm_Mock : public Alarm
{
public:
    Alarm_Mock();
    virtual ~Alarm_Mock();

    MOCK_METHOD1(getType, ENUM_TYPE(ENUM_TYPE ENUMONE));
};

Google Test:

class Ev_test: public testing::Test
{
    void SetUp()
    {
        mpsEV= new CEvents();
        ON_CALL(msMock, getType(_)).WillByDefault(Return(SOME_ENUM));
    }

    void TearDown()
    {
        delete mpsEV;
    }

protected:
    Alarm_Mock msMock;  
    CEvents* mpsEV;
};

TEST_F(Ev_test, testGetFunctions)
{   
    EXPECT_CALL(msMock, getAlarmType(_))
            .Times(1);

    mpsEV->aMethod(arg1, arg2, arg3, arg4);
}

Class Method to Test - Does getType from Class Alarm get called?:

void CEvents::aMethod(arg1, arg2, arg3, arg4)
{
    Alarm::find()->getType(arg1);
}
273K
  • 29,503
  • 10
  • 41
  • 64
JC203
  • 384
  • 7
  • 18
  • I am not familiar with Google Mock. I might be off regarding what can be tested with it but it appears that you can't test `static` member functions. See https://groups.google.com/forum/#!topic/googlemock/ixT92RTY350. But then, that was in 2012. It may not be valid today. – R Sahu Apr 13 '17 at 20:59
  • 1
    Off topic: The Meyers Singleton may be of use to you. Good write-up here: http://stackoverflow.com/a/1008289/4581301 – user4581301 Apr 13 '17 at 21:05
  • @user4581301 and @R Sahu I've been told by a co-worker to look into Alias. I am investigating this now. – JC203 Apr 18 '17 at 00:20

1 Answers1

0

CEvents::aMethod() invokes getType(arg1) on the instance returned by Alarm::find(), which will be different from your mock object.

A quick fix would be to move the assignment of Alarm::Alarm_Instance out of Alarm::find() and into Alarm::Alarm().

Ludwig Schulze
  • 2,155
  • 1
  • 17
  • 36
  • wouldn't that make my class not a singleton anymore? – JC203 Apr 28 '17 at 21:00
  • @JC203 It makes it even more a singleton than what you have right now. You have a public constructor and users can bypass the factory method, creating additional instances without restriction (e.g. with new). This would be prevented you add this assignment to the constructor and throw an exception if the static singleton pointer was already not NULL. – Ludwig Schulze Apr 29 '17 at 08:28