问题
I've got a class and member:
class A
{
B obj;
public:
int f(int i){return obj.g(i);}
}
Here "B obj" is a dependency that requires run-time creation from a file. In my unit test for class A, I wish to mock "B obj", with a function g typed int(int).
How can I write my test code, to mock "B obj", and then test A::f.
Thanks a lot.
回答1:
You need to use dependency injection to achieve this. To this end, have class B
inherit from an interface, and have class A
hold a pointer to that interface:
class IB
{
public:
virtual void g(int i) = 0;
};
class B : public IB
{
public:
void g(int i) {
// this is your real implementation
}
};
Also, to enable dependency injection in class A
, add appropriate constructor or setter method:
class A
{
private:
IB *obj;
public:
A() : obj(nullptr) {}
// You don't need both the constructor and setter, one is enough
A(IB *pB) : obj(pB) {}
// void setB(IB *pB) { obj = pB; }
int f(int i) { return obj->g(i); }
};
Now, in your production code you create an object of class B
and pass it to class A
object (assuming that we are using the constructor for injection):
B b;
A a(&b);
During testing phase, you create a mock class BMock
and pass an object of that class to class A
object:
class BMock : public IB
{
public:
MOCK_METHOD1(g, int(int));
};
TEST(ATests, TestCase1)
{
BMock bmock;
A a(&bmock);
// Now you can set expectations on mock object, for example that g will
// return 100 when it receives 50 as argument
EXPECT_CALL(bmock, g(50)).WillOnce(Return(100));
// Now act by calling A::f, which will in turn call g from mock object,
// and assert on function return value
ASSERT_EQ(a.f(50), 100);
}
回答2:
To do this, take a pointer of B instead of object in class A
and make your unit Test class (FixtureA
) as friend class
in A
.
class A
{
B *obj;
public:
int f(int i){return obj.g(i);}
friend class FixtureA;
};
In FixtureA.h
you can have following code
class FixtureA
{
public:
void Testf();
}
In FixtureA.cpp
TEST_F(FixtureA , Testf)
{
Testf();
}
void FixtureA::Testf()
{
A objA;
objA.obj = new BMock();
objA.f(2);
}
In BMock class
, you can mock the g()
function.
回答3:
You can't do it with the code you have. You have hardcoded your dependency inside the A
class. To make mocking possible you have to use some of the dependency injection patterns. One of the possible ways is to have a pointer(better smart) to your B
class and in the A
constructor you will get a pointer to B
with which you will initialize your inner B*
. That way you will be able to put a mocked object in your tests.
来源:https://stackoverflow.com/questions/37130444/how-to-mock-a-member-variable-of-dependency