如何使用shared_ptr从外部提供模拟对象? [英] How to use shared_ptr to supply mock object from outside?

查看:106
本文介绍了如何使用shared_ptr从外部提供模拟对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试一个使用资源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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆