I am trying to figure out how FRIEND_TEST works in Google Tests.
https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#testing-private-code
I am looking at the following item, trying to implement it in my code:
// 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().
}
In the code above, the piece that I can’t see, is that foo_test.cc must include foo.h, in order to have access to Foo and Bar(). [Perhaps it works differently for Google ? in my code, I must include it]
That will result in circular dependency…
Am I missing something ?
Edit: code sample: (re-edited after fixing – solution being changing test file from *.h to *.cpp):
Project ppppp – file myfile.h:
class INeedToBeTested
{
public:
extern friend class blah_WantToTestThis_Test;
INeedToBeTested();
INeedToBeTested(INeedToBeTested* item);
INeedToBeTested(OtherClass* thing, const char* filename);
~INeedToBeTested();
bool Testable();
std::string MoreTestable();
private:
int WantToTestThis();
};
Project ppppp_gtest, file myFile_gtest.cpp:
#pragma once
#include "gtest/gtest.h"
#include "myfile.h" //property sheet adds include locations
#include "otherclass.h"
class blah: public ::testing::Test{
// declarations, SetUp, TearDown to initialize otherclass thing, std::string filename
}
TEST_F(blah, WantToTestThis)
{
INeedToBeTested item(thing, filename.c_str());
item.WantToTestThis(); // inaccessible when this content is in header file
}
During my efforts to get this to work, I also experimented with creating a wrapper class (this also works only if in a cpp, not in header); while it requires changing private to protected, it doesn’t require additional declarations inside tested code which each new test:
// option: create wrapper (change private to protected first)
class INeedToBeTestedWrapper:public INeedToBeTested
{
public:
INeedToBeTestedWrapper(OtherClass* thing, std::string filename):
INeedToBeTested(OtherClass* thing, filename.c_str());
public:
using INeedToBeTested::WantToTestThis;
};
TEST_F(blah, WantToTestThis)
{
INeedToBeTestedWrapper item(thing, filename);
item.WantToTestThis();
}
There shouldn’t be a problem here.
FRIEND_TESTin this case simply defineswhich is the class ultimately defined by using the
TESTmacro. There’s no need to link gtest or any of your test code to thefoolibrary/exe. You only need to#include "gtest/gtest_prod.h"as you have done.In foo_test.cc, you need to
#include "foo.h"since it’s using an actual instance of aFooobject. You also need to link yourfoolibrary to the test executable, or iffooisn’t a library, you need to compile in thefoosources.So in summary,
foodoesn’t need any test code with the exception of the tiny gtest_prod.h header, but the test needs linked to thefoocode.