I know that this question is already a few years old but I stumbled upon this in search of a better solution for exactly the same problem. Indeed, I do have two possible solutions - none of them is elegant or simple but they do work so I want to share them here in case someone else still has the same problem.
I'll assume you're using gcc and ld here but of course those methods should work with any other compiler, too (at least the second one).
Secondly, I'll assume, you have 4 files by now, A.hpp, A.cpp, B.cpp and B.hpp with the following content (of course, if you combine A.hpp and A.cpp, it will work as well...):
A.hpp:
#include "B.hpp" class A { B obj; public: int f(int i); };
A.cpp:
#include "A.hpp" int A::f(int i){ return obj.g(i); }
B.hpp:
class B { public: int g(int i); };
B.cpp includes the implementation of B::g().
Method 1 is possible, if you have a folder structure where B.hpp is not in the same folder as A.cpp or if you replace line 1 in A.cpp by #include <B.hpp> (I think this is compiler/preprocessor dependant but I'm not sure on that one. Afaik, gcc always searches in . first, if you include with ")
In this case, you can create another B.hpp:
#include <gmock/gmock.h> class B { public: MOCK_METHOD(int, g, (int), ()); };
Now, you must change your commandline to something like
g++ A.cpp -I./Testing/B -o A.o
where the new B.hpp lies in ./Testing/B. Furthermore, you must remove B.cpp from your pipeline when building the tests.
Be aware that this method changes what's included in your original cpp file and therefore changes its object. If you don't be careful enough there is a certain chance that your test behaves different to your real system!
Method 2: You can use that one if B.hpp is in the same folder as A.cpp and you have a code using #include "B.hpp" . In this case, the compiler will most probably use the B.hpp inside the source folder instead of the one given with the -I flag. I consider this method superior as it doesn't change the compile unit A.o but on the other hand its much more work to do.
Create two files: Bmock.hpp:
#include <gmock/gmock.h> class Bmock{ public: MOCK_METHOD(int,g,(int),()); };
B.cpp
#include <B.hpp> #include <Bmock.hpp> extern Bmock* bmock; int B::g(int i){ return bmock->g(i); }
Now, during your linking step, have to replace your original B.o file with the new one.
Inside your Test Suite:
#include <Bmock.hpp> #include <A.hpp> #include <gtest/gtest.h> Bmock* bmock; class UT_A:public ::testing::Test{ public: void SetUp() override{ bmock=new bmock(); } void TearDown() override{ delete bmock; } A uut; }; TEST_F(UT_A,test_g){ EXPECT_CALL(*bmock,g(5)).WillOnce(Return(3)); ASSERT_EQ(uut.f(5),3); }
Using this method, your compile unit A.o can be left untouched and should therefore behave as in the real system.
I hope this is of use for someone!
Greetings
Ashould hold an interface implemented byBinstead of a concrete instance.B. Also, if you find the answer helpful, consider up-voting and/or marking the answer as accepted.