代码之家  ›  专栏  ›  技术社区  ›  rranjik

如何使用shared\u ptr从外部提供模拟对象?

  •  2
  • rranjik  · 技术社区  · 7 年前

    我想测试一个应用程序 Thud ,将使用资源 Foo . 它不会拥有一个具体的对象,但会有一个指向抽象资源接口的指针( IFoo 这里)。在生产中,我将为其提供实际的资源实现( FooImpl )而对于单元测试,我想发送一个指向模拟资源的指针。我该怎么做?我试着写最少的代码来达到目的,

    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();
    }
    

    所以为了完成,我有一个重载构造函数,它不接受参数,但将执行以下操作,

    Thud():fooPtr {std::make_shared<FooImpl>()}
    {}
    

    以在生产中得到真正的实施。

    shared_ptr 相反,在第一个测试用例之后,它会因堆损坏而崩溃。

    它与这个原始指针完美配合。

    3 回复  |  直到 7 年前
        1
  •  3
  •   Angew is no longer proud of SO    7 年前

    你做不到 foo.reset(&mock) 从那时起 mock foo . 内存损坏FTW。

    您只需分配 FooMock 并在创建 Thud 正在测试的实例:

    class ThudTest : public ::testing::Test
    {
    protected:
        virtual void SetUp() {
            foo = std::make_shared<FooMock>();
        }
    
        std::shared_ptr<FooMock> foo;
    };
    

    你甚至不需要 嘲弄 不再是会员。注意,我更改了 了解 FooMock公司 ,以便您可以访问该类型。如果你真的想 要保持不知情,请这样做:

    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> .

        2
  •  2
  •   Jarod42    7 年前

    使用:

    class Thud
    {
        std::shared_ptr<IFoo> fooPtr;
    public:
        Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
        {}
        bool thud1(bool b)
        {
            return fooPtr->Foo(b);
        }
    };
    

    您的测试可以变成(我删除了该功能):

    TEST(ThudTest, fooFalse)
    {
        auto mock = std::make_shared<FooMock>()
        bool b = false;
        EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(false));;
    
        Thud thud(mock);
        EXPECT_FALSE(thud.thud1(b));
    }
    
    TEST(ThudTest, fooTrue)
    {
        auto mock = std::make_shared<FooMock>()
        bool b = true;
        EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(true));;
    
        Thud thud(mock);
        EXPECT_TRUE(thud.thud1(b));
    }
    
        3
  •  1
  •   Paweł Iwaneczko    4 年前

    在我的解决方案中,需要使用 shared_ptr<IFoo> 为了将其添加到其他测试类中的集合中,我想出了使用referecne;)。然后我试着 NiceMock<IFoo> StrictMock<IFoo>

    using namespace testing;
    using namespace std;
    
    class ThudTest : public Test {
      public:
        shared_ptr<FooMock> fooPtr_ = make_shared<FooMock>();
        // shared_ptr<StrictMock<FooMock>> fooPtr_ = make_shared<StrictMock<FooMock>>();
        FooMock& mock = *fooPtr_;
        // StrictMock<FooMock>& mock= *fooPtr_;
    
        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));
    
        EXPECT_FALSE(thud1(b));
    }
    
    TEST_F(ThudTest, fooTrue) {
        bool b = true;
        EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));
    
        EXPECT_TRUE(thud1(b));
    }