简体   繁体   中英

Expect matcher for reference object with GoogleMock in C++

I'm attempting to use mocks to test that a certain method was called with certain arguments and am having trouble testing that *this is one of the arguments.

Here's the code under test:

class Component
{
  virtual void update(Entity &entity, const uint32_t dt) {};
  ...

void Entity::update(const uint32_t dt)
{
  for (unsigned int i = 0; i < components_.size(); ++i) {
    components_[i]->update(*this, dt);
  }
}   

And the test:

ea_ = new aronnax::Entity(cla_);
EXPECT_CALL(mockComponent, update(Eq(ByRef(ea_)), testDt)).Times(1);
ea_->update(testDt);

I'm getting errors that the two types aren't comparable. I'm relatively new to c++ and am having trouble understanding how to compare the pointer ea_ to the pointer reference ( *& ) to ea_ passed into update .

Here's a complete working example. Note that the component method update must be declared with one of the MOCK_METHOD* macros. To check if an argument is a reference to some type, you use the Ref matcher. To bind to the reference with a pointer type, you must dereference the pointer as seen in the example.

Also, its important to understand that you must set the expectations on the object that is actually going to be called. I can't tell if your mock component is in the components container or not in your entity class, but I demonstrate the problems with not setting expectations on the correct object in the commented out portion in the test.

#include <stdint.h>
#include <gmock/gmock.h>

class Entity;

class Component
{
public:
   MOCK_METHOD2(update, void(Entity&, uint32_t));
};

class Entity
{
public:
   Entity(Component* c) : c_( c )
   {
   }

   void update(uint32_t dt)
   {
       c_->update(*this, dt);
   }

private:
   Component* c_;
};

using ::testing::Ref;

TEST(MyTest, Component)
{
   Component mockComponent;
   Entity* ea = new Entity( &mockComponent );
   EXPECT_CALL(mockComponent, update(Ref(*ea), 5));
   ea->update( 5 );

   // Component mockComponent2;
   // Entity* ea2 = new Entity( &mockComponent );
   // EXPECT_CALL(mockComponent2, update(Ref(*ea2), 5));
   // ea2->update( 5 );
}

You may not need this, but it should allow you to quickly build the example if you have cmake.

cmake_minimum_required(VERSION 3.4)

include(CTest)
include(ExternalProject)

# Add googletest
ExternalProject_Add( googletest
    GIT_REPOSITORY https://github.com/google/googletest.git

    CMAKE_ARGS = "-Dgtest_disable_pthreads=1"

    # Don't run update
    UPDATE_COMMAND ""

    # Disable install step
    INSTALL_COMMAND ""

   # BUILD_BYPRODUCTS googletest-prefix/src/googletest-stamp/googletest-gitinfo.txt
   # BUILD_BYPRODUCTS googletest-prefix/tmp/googletest-cfgcmd.txt
    BUILD_BYPRODUCTS "googletest-prefix/src/googletest-build/googlemock/libgmock_main.a"
    )
# Get include dirs for googletest framework
ExternalProject_Get_Property(googletest source_dir)
set(GTEST_INCLUDE_DIRS
   ${source_dir}/googlemock/include
   ${source_dir}/googletest/include
   )

# Create library target for gmock main, which is used to create
# test executables
ExternalProject_Get_Property(googletest binary_dir)
set(GTEST_LIBRARY_PATH ${binary_dir}/googlemock/libgmock_main.a)
set(GTEST_LIBRARY gmock_main)
add_library(${GTEST_LIBRARY} UNKNOWN IMPORTED)
set_property(TARGET ${GTEST_LIBRARY} PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARY_PATH})
add_dependencies(${GTEST_LIBRARY} googletest)

add_executable(mytest main.cpp)
add_dependencies(mytest googletest)
target_include_directories(mytest BEFORE PRIVATE ${GTEST_INCLUDE_DIRS})
target_link_libraries(mytest gmock_main)

add_test(NAME mytest COMMAND mytest)

If you run the example, it should give you the following output.

$ ./mytest.exe
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MyTest
[ RUN      ] MyTest.Component
[       OK ] MyTest.Component (0 ms)
[----------] 1 test from MyTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.

Hope this helps you :

instead of:

ea_ = new aronnax::Entity(cla_);
EXPECT_CALL(mockComponent, update(Eq(ByRef(ea_)), testDt)).Times(1);
ea_->update(testDt);

you should convert you pointer to a reference (note * inside ByRef):

ea_ = new aronnax::Entity(cla_);
EXPECT_CALL(mockComponent, update(Eq(ByRef(*ea_)), testDt)).Times(1);
ea_->update(testDt);

or simply define the object on the stack and pass it as is (it will be passed as a reference by the compiler):

aronnax::Entity ea_(cla_); // NOT a pointer any more
EXPECT_CALL(mockComponent, update(Eq(ByRef(ea_)), testDt)).Times(1);<br>
ea_->update(testDt);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM