【问题标题】:C++ Google mock/unit tests : Mock method not called and original one isC ++ Google模拟/单元测试:未调用模拟方法,原始方法是
【发布时间】:2018-07-18 11:53:44
【问题描述】:

我在模拟一个方法,但我的 GoogleTest 似乎一直在调用原始实现。可能遗漏了什么,但找不到这是什么?

我的班级是 Postgres 数据库访问器:

namespace project
{

class PostgresDb
{
public :
    // typedef the CursorPtr, this is just a smart pointer.
    // sth like 
    typedef shared_ptr<DbDataType> CursorPtr ;

    PostgresDb( const std::string & connString ) ;

    CursorPtr getRecords( const int id_1 ,
                          const int id_2 ) ;

protected :

    // this will be used by the MockPostgresDb in our unit tests.
    // it leaves the object uninitialized
     PostgresDb (){} ;

 }

}// end of namespace

这是我的模拟课:

namespace project_test
{

class MockPostgresDb : public project::PostgresDb
{
public :
    MockPostgresDb(){} ;
    MOCK_METHOD2( getRecords, CursorPtr*( const int , const int  ) ) ;
} ;

class MockCursor : public CursorPtr
{
    // ....
}

}

这是我正在测试的方法和测试:

void original_get_method( const int id_1, const int id_2 , PostgresDb db)
{
    // ....
    db.getRecords( id_1, id_2 ) ;
    // ....
}

// helper function
setupGetRecords( MockPostgresDb* db     ,
                 MockCursor*     cursor ) 
{
    EXPECT_CALL( *db, getRecords(_,_) )
        .Times( 1 )
        .WillRepeatedly(::testing::Return( cursor ) ) ;
}


TEST_F(....)
{
    MockPostgresDb db ;
    MockCursor     cursor ;
    // ....
    setupGetRecords( &db, &cursor ) ; 
    // ....
    // and then calling a functi
    original_method( id_1, id_2, db ) ;
}

所以在我看来,我打电话给original_method 并传递一个mock_dbmock_db 调用它的方法getRecords,它返回一个MockCursor。这是它应该让我模拟的地方,但我确实输入了db::getRecords

我试图找出不匹配的位置,但无法弄清楚。

编辑:

因此,正如所指出的 - getRecords 应该返回 CursorPtr 而不是 CursorPtr*。所以这就是我所做的:

我也尝试过改变

MOCK_METHOD2( getRecords, CursorPtr*( const int , const int  ) ) ;`

MOCK_METHOD2( getRecords, CursorPtr( const int , const int  ) ) ;  // ( no * ) 

并将助手更改为

// helper function
setupGetRecords( MockPostgresDb* db     ,
                 MockCursor     cursor ) 
{
    EXPECT_CALL( *db, getRecords(_,_) )
        .Times( 1 )
        .WillRepeatedly(::testing::Return( cursor ) ) ;
}

并得到一些不匹配类型的编译错误。什么地方出了错?谢谢。

【问题讨论】:

  • getRecords 返回CursorPtr 类型的对象,而你的模拟方法试图返回CursorPtr* 这是两种不同的方法。 ( no * ) 是什么意思?这似乎是导致编译器错误的原因。
  • @Yksisarvinen 好的,让我重试,但返回 CursorPtr 给了我很多编译错误。
  • 你得到什么样的编译器错误?请编辑问题并添加它们(复制并粘贴它们,不要解释)。
  • 你保护了PostgresDb构造函数,你不是在任何地方创建那个类的对象吗?
  • @Yksisarvinen public 参数是一个字符串,protected 仅适用于使用它的 Mock 类。参数是 db 连接到的环境,但 Mock 不需要它。编辑我的答案。

标签: c++ unit-testing googlemock


【解决方案1】:

这里的主要问题是在函数void original_get_method( const int id_1, const int id_2 , PostgresDb db)PostgresDb 是按值传递的,即会调用PostgresDb 的复制构造函数。这意味着在original_get_method 函数内部,您没有MockPostgresDb-Object,而是一个简单的PostgresDb,这就是为什么不调用模拟方法而只是调用原始实现的原因。此外,getRecords 函数不是虚拟的,即 MockPostgresDb 类中的模拟方法只是隐藏了 PostgresDb 的函数(因此无法在运行时告诉程序调用哪个函数,即如果有PostgresDb-Object 或对此类对象的引用,它将始终调用该类中的函数。

所以首先要改变:

class PostgresDb
{
public :
    // typedef the CursorPtr, this is just a smart pointer.
    // sth like 
    typedef shared_ptr<DbDataType> CursorPtr ;

    PostgresDb( const std::string & connString ) ;

    // ===> make this method virtual <====
    virtual CursorPtr getRecords( const int id_1 ,
                          const int id_2 ) ;
}

// pass PostgresDb by reference
void original_get_method( const int id_1, const int id_2 , PostgresDb& db);

这两个变化会调用original_get_method中的mocked方法。


下一个问题正如 cmets 中指出的那样:

MOCK_METHOD2( getRecords, CursorPtr*( const int , const int  ) ) ;

模拟方法具有不同的签名,然后基类 -> 函数不会在派生(模拟)类中被覆盖(即它们是两个完全不同的函数)。这就是你想要的:

MOCK_METHOD2( getRecords, CursorPtr( const int , const int  ) ) ;

下一个问题如下:

typedef shared_ptr<DbDataType> CursorPtr ;

你定义你的新类型CursorPtr,然后从它继承

class MockCursor : public CursorPtr {}

但是MockCursor 不是继承自DbDataType 而是继承自std::shared_ptr,即它们完全不同。而是让MockDbDataType 继承自DbDataType 并创建一个新类型MockCursor

typedef std::shared_ptr<MockDbDataType> MockCursor;

然后这应该可以正常编译:

setupGetRecords( MockPostgresDb* db     ,
                 MockCursor     cursor ) 
{
    EXPECT_CALL( *db, getRecords(_,_) )
        .Times( 1 )
        .WillRepeatedly(::testing::Return( cursor ) ) ;
}

我没有测试过这段代码,所以如果有任何问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2014-04-16
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2019-09-14
    • 2014-06-07
    相关资源
    最近更新 更多