如何使用shared_ptr从外部提供模拟对象? [英] How to use shared_ptr to supply mock object from outside?
问题描述
我想测试一个使用资源Foo
的应用程序Thud
.它不会拥有具体的对象,但是将具有指向抽象资源接口的指针(此处为IFoo
).在生产中,我将为它提供实际的资源实现(FooImpl
),而对于单元测试,我想发送一个指向模拟资源的指针.我该怎么办?我试图编写最少的代码只是为了指出要点,
I want to test an app Thud
, which will use a resource Foo
. It will not own a concrete object but will have a pointer to a abstract resource interface (IFoo
here). In production I will supply it with the actual resource implementation (FooImpl
) whereas for unit test I want to send a pointer to a mock resource. How should I do this ? I've tried to write the least code just to get to point,
class IFoo
{
public:
virtual bool Foo(bool) = 0;
};
class FooImpl : public IFoo
{
public:
bool Foo(bool b) override
{
return b;
}
};
class FooMock : public IFoo
{
public:
MOCK_METHOD1(Foo, bool(bool));
};
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
//foo.reset(&mock); //line#1
foo = &mock; //line#2
}
FooMock mock;
//std::shared_ptr<IFoo> foo; //line#3
IFoo* foo; //line#4
};
class Thud
{
//std::shared_ptr<IFoo> fooPtr; //line#5
IFoo* fooPtr; //line#6
public:
/*Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
{}*/ //line#7
Thud(IFoo* fooPtr_) : fooPtr{ fooPtr_ }
{} //line#8
bool thud1(bool b)
{
return fooPtr->Foo(b);
}
};
TEST_F(ThudTest, fooFalse)
{
bool b = false;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(false));;
Thud thud(foo);
EXPECT_FALSE(thud.thud1(b));
}
TEST_F(ThudTest, fooTrue)
{
bool b = true;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));;
Thud thud(foo);
EXPECT_TRUE(thud.thud1(b));
}
int main(int argc, char** argv) {
// The following line must be executed to initialize Google Mock
// (and Google Test) before running the tests.
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
因此,为了完整起见,我有一个重载的构造函数,它不需要争论,但是会执行以下操作,
So for completion I've has an overloaded constructor that takes not arguement but will do the following,
Thud():fooPtr {std::make_shared<FooImpl>()}
{}
在生产中得到真正的实现. 但是现在我该如何使指针指向模拟对象.如您所见,我在这里使用GMock框架.如何实现呢?
to get the real implementation in production. But now how do I make the pointer point to the mock object. As you can see, I'm using GMock framework here. How to achieve this ?
如果我注释#2,4,6行& 8使用普通的原始原始指针并取消注释,并使用行#1,3,5& 7(此处使用有问题的shared_ptr
),则在第一个测试用例之后它会由于堆损坏而崩溃.
If I comment out line #2,4,6 & 8 which uses a plain old raw pointer and uncomment and use line #1,3,5 & 7 (using the shared_ptr
in question here) instead, it crashes with heap corruption after the first test case.
它与该原始指针完美配合.
It works perfectly with this raw pointer.
推荐答案
您不能执行foo.reset(&mock)
,因为mock
具有两个所有者:它的自动存储持续时间,以及共享指针foo
.内存损坏FTW.
You cannot do foo.reset(&mock)
, since then mock
has two owners: its automatic storage duration, plus the shared pointer foo
. Memory corruption FTW.
您应该简单地动态分配FooMock
并在创建要测试的Thud
实例时将其传递:
You should simply allocate the FooMock
dynamically and pass it in when creating the Thud
instance being tested:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
foo = std::make_shared<FooMock>();
}
std::shared_ptr<FooMock> foo;
};
您甚至不再需要mock
成员.请注意,我已经更改了foo
的类型以了解FooMock
,以便您可以访问该类型.如果您确实希望foo
保持对模拟的了解,请执行以下操作:
You won't even need the mock
member any more. Note that I've changed the type of foo
to know about FooMock
, so that you can access that type. If you really want foo
to remain mock-unaware, do it like this:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
mock = std::make_shared<FooMock>();
foo = mock;
}
std::shared_ptr<FooMock> mock;
std::shared_ptr<IFoo> foo;
};
但是,这不是必需的,因为std::shared_ptr<FooMock>
可隐式转换为std::shared_ptr<IFoo>
.
However, this should not be necessary, since std::shared_ptr<FooMock>
is implicitly convertible to std::shared_ptr<IFoo>
.
这篇关于如何使用shared_ptr从外部提供模拟对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!