Reputation: 5259
I am mocking a method but it seems that my GoogleTest
keeps calling the original implementation. Probably missing something but can't find out what is this?
My class is a Postgres database accessor:
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
and here is my mock class:
namespace project_test
{
class MockPostgresDb : public project::PostgresDb
{
public :
MockPostgresDb(){} ;
MOCK_METHOD2( getRecords, CursorPtr*( const int , const int ) ) ;
} ;
class MockCursor : public CursorPtr
{
// ....
}
}
and here is the method I am testing and the test:
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 ) ;
}
So in my mind, I am calling original_method
and pass a mock_db
. The mock_db
calls its method getRecords
which returns a MockCursor
. This is where it should get me the mock one but I do enter the db::getRecords
.
I am trying to find where the mismatch is but cannot figure out.
EDIT :
So, as pointed out - getRecords
should return a CursorPtr
and not a CursorPtr*
. So here is what I did:
I also tried to change
MOCK_METHOD2( getRecords, CursorPtr*( const int , const int ) ) ;`
to
MOCK_METHOD2( getRecords, CursorPtr( const int , const int ) ) ; // ( no * )
And change the helper to
// helper function
setupGetRecords( MockPostgresDb* db ,
MockCursor cursor )
{
EXPECT_CALL( *db, getRecords(_,_) )
.Times( 1 )
.WillRepeatedly(::testing::Return( cursor ) ) ;
}
and getting some mismatched types of compilation errors. What went wrong? Thanks.
Upvotes: 3
Views: 8585
Reputation: 2878
The main problem here is that in the function void original_get_method( const int id_1, const int id_2 , PostgresDb db)
the PostgresDb
is passed by value, i.e. the copy constructor of PostgresDb will be called. This means that inside of the original_get_method
function you don't have a MockPostgresDb
-Object but a simple PostgresDb
and that's why not the mocked method gets called but simply the original implementation. Furthermore the getRecords
function is not virtual, i.e. the mocked method in class MockPostgresDb
just shadows the function of PostgresDb
(and so there's no way to tell the program at run-time which function to call, i.e. if there is a PostgresDb
-Object or reference to such an object it will always call the function in that class).
So first things to change:
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);
These two changes will call the mocked method in original_get_method
.
Next problem is as pointed out in the comments:
MOCK_METHOD2( getRecords, CursorPtr*( const int , const int ) ) ;
The mock method has a different signature then the base class -> function will not get overwritten in derived (mocked) class (i.e. they are two completely different functions). This is what you want:
MOCK_METHOD2( getRecords, CursorPtr( const int , const int ) ) ;
Next problem is the following:
typedef shared_ptr<DbDataType> CursorPtr ;
You define your new type CursorPtr
and then inherit from it
class MockCursor : public CursorPtr {}
But MockCursor
does not inherit from DbDataType
but from std::shared_ptr
, i.e. they are nothing alike. Instead let MockDbDataType
inherit from DbDataType
and create a new type MockCursor
:
typedef std::shared_ptr<MockDbDataType> MockCursor;
And then this should compile fine:
setupGetRecords( MockPostgresDb* db ,
MockCursor cursor )
{
EXPECT_CALL( *db, getRecords(_,_) )
.Times( 1 )
.WillRepeatedly(::testing::Return( cursor ) ) ;
}
I haven't tested this code, so if there are any problems let me know.
Upvotes: 4