Home > Net >  Accessing private members inside a MATCHER
Accessing private members inside a MATCHER

Time:10-14

I am verifying the private members of Object (Values storing the internal state of the class) via a MATCHER in a unit test however I have the following concern:

  • I created GetValueA() and GetValueB() public interfaces solely so that unit test could access inside a MATCHER. Doesn't sound like a right idea (specially if it's not supposed to be publicly exposed) but is there a way to access valueA and valueB inside a MATCHER somehow without having to create public methods? (could be set to private/protected perhaps so it's not publicly exposed)

MATCHER_P2 could be brought inside the Object class but how would the caller invoke it?

Live sample

template<typename T>
class Object
{
    // internal to the class
    struct Values
    {
        int valueA = 100;
        int valueB = 0;
    };

    Values values = {};
    T otherStuff;

    public:
    // only exposing for the sake of Unit test access
    int GetValueA() const
    {
        return values.valueA;
    }

    int GetValueB() const
    {
        return values.valueA;
    }
};

MATCHER_P2(Match, m1, m2, "")
{
    return ExplainMatchResult(m1, arg.GetValueA(), result_listener) &&
           ExplainMatchResult(m2, arg.GetValueB(), result_listener);
}

class UnitTest 
{
  TEST(UnitTest, testA)
  {
     Object<int> object;
     EXPECT_THAT(object, Match(Ne(0), Eq(0))); 
  }
};

CodePudding user response:

You can pass the private member to the matcher, and define the test to be a friend class.

Also use FRIEND_TEST macro instead of friend class.

template<typename T>
class Object
{
    // internal to the class
    struct Values
    {
        int valueA = 42;
        int valueB = 0;
    };
    FRIEND_TEST(UnitTest, testA);
    Values values = {};
    T otherStuff;

};

MATCHER_P2(Match, m1, m2, "")
{
    return ExplainMatchResult(m1, arg.valueA, result_listener) &&
        ExplainMatchResult(m2, arg.valueB, result_listener);
}

TEST(UnitTest, testA)
{
    Object<int> object;
    EXPECT_THAT(object.values, Match(Ne(0), Eq(0)));
}

Live example: https://godbolt.org/z/WWr3vrWsn

CodePudding user response:

As mention in the comments, in principle is not the best idea to unit test private members, but sometimes that is what you want/need.

If this is the case, you might want to go making the testclass a friend class:

template<typename T>
class Object
{
    friend class UnitTest_testA_Test; // pay attention to the name
                                      // it should be Test at the end (Uppercase 'T')
    struct Values
    {
        int valueA = 42;
        int valueB = 0;
    };
};

TEST(UnitTest, testA)
{
    Object<int>  object;
    EXPECT_EQ(42, object.values.valueA);
}

And since you want to use a matcher:

MATCHER_P2(Match, m1, m2, "")
{
    return ExplainMatchResult(m1, arg.values.valueA, result_listener) &&
           ExplainMatchResult(m2, arg.values.valueB, result_listener);
}
  • Related