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()
andGetValueB()
public interfaces solely so that unit test could access inside aMATCHER
. Doesn't sound like a right idea (specially if it's not supposed to be publicly exposed) but is there a way to accessvalueA
andvalueB
inside aMATCHER
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?
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);
}