I heard there is a possibility to enable google-test TestCase classes friends to my classes, thus enabling tests to access my private/protected members.
How to accomplish that?
I heard there is a possibility to enable google-test TestCase classes friends to my classes, thus enabling tests to access my private/protected members.
How to accomplish that?
Try this (straight from Google Test docs...):
FRIEND_TEST(TestCaseName, TestName);
For example:
// foo.h
#include <gtest/gtest_prod.h>
// Defines FRIEND_TEST.
class Foo {
...
private:
FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
int Bar(void* x);
};
// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
Foo foo;
EXPECT_EQ(0, foo.Bar(NULL));
// Uses Foo's private member Bar().
}
Foo
? –
Ovipositor gtest_prod.h
–
Oaks I know this is old but I was searching for the same answer today. "gtest_prod.h" just introduces a simple macro to reference test classes.
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
So FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
is equivalent to:
friend class FooTest_BarReturnsZeroOnNull_Test;
This works because each test is its own class as mentioned in the previous answer.
A far better strategy is to not allow friend tests among your unit tests.
Allowing friend tests accessing private members will lead to a code base that is hard to maintain. Tests that break whenever a component's inner implementation details are refactored is not what you want. If extra effort is instead put into getting a design where components can be tested through their public interface, you will get tests that only need updating whenever the public interface of a component is updated.
Tests relying on gtest/gtest_prod.h
should be seen as a sign of poor design.
friend
for testing is always a bad idea. –
Mordvin When your tested class and your test class are in a different namespace (e.g. your tests are in the global namespace), you may need to forward-declare your test class and add your namespace prefix in FRIEND_TEST
:
// foo.h
#include <gtest/gtest_prod.h>
// forward-declaration of test class
class FooTest_BarReturnsZeroOnNull_Test;
// Defines FRIEND_TEST.
class my_namespace::Foo {
...
private:
// Specify the global namespace (`::`) in the `FRIEND_TEST()` usage
FRIEND_TEST(::FooTest, BarReturnsZeroOnNull);
int Bar(void* x);
};
// forward-declaration of this namespace from foo_test.cc
using namespace my_namespace;
...
TEST(FooTest, BarReturnsZeroOnNull) {
Foo foo;
EXPECT_EQ(0, foo.Bar(NULL));
// Uses Foo's private member Bar().
}
I know that friend unit tests (or the friendliness in C++ in general) and white-box testing are a controversial subject, but when you work on complex, scientific algorithms, each step of which you need to test and validate, but that you don't want to expose in public (or even protected) interfaces, friend tests appear to me as a simple and pragmatic solution, especially in a test-driven development approach. It is always possible to refactor the code later (or to completely remove white-box tests) if it's against one's religion to use the friendliness or white-box testing.
If you don't want to have to individually list each test case with FRIEND_TEST
, another option is to define a test fixture class and then friend that instead:
class Foo
{
...
private:
friend class FooTest;
};
...
class FooTest : public ::testing::Test
{
protected:
int AccessPrivateFooThing(Foo& foo) { ... }
...
};
...
TEST_F(FooTest, PrivateThing)
{
...
int result = AccessPrivateFooThing(foo);
...
}
However a caveat with this is that only methods defined in the test fixture itself will have access to Foo
's private members; the tests themselves will not. You'll have to define accessors, bouncers, or other helper methods within the fixture where that access is required. This requires a bit more boilerplate than some other solutions, but is also more explicit, which hopefully discourages too much reaching into internals.
If you encounter issues with namespaces, simply ensure that the test fixture is in the same namespace as the class in question; this is a good practice anyway.
It's still strongly encouraged to test only public members where reasonably feasible, though I do agree that there are some times where this makes more sense.
© 2022 - 2024 — McMap. All rights reserved.
#define private public
before including the definition of the class being tested. – Axes#define private public
solution may not always be applicable as you may link against the actual unit (i.e. built without this re-#definition) possibly leading to missing linker symbols. In this case theFRIEND_TEST
solution can help. All in all I would also recommend restricting the use of either solution to legacy code that can't / shouldn't be refactored. New code shall be directly designed for testability. – Visit