C++ 谷歌模拟/单元测试:模拟方法未调用,原始方法是

C++ Google mock/unit tests : Mock method not called and original one is

本文关键字:模拟 方法 调用 原始 谷歌 单元测试 C++      更新时间:2023-10-16

我在嘲笑一种方法,但似乎我的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_db.mock_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 ) ) ;
}

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

这里的主要问题是,在函数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中调用模拟方法。


下一个问题如评论中指出的那样:

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

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

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

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