Search code examples
c++unit-testinggoogletestgooglemock

Mock function called by aggregate object using googlemock


I have s scenario where in a local object is instantiated to call a method of that class i.e setSessionId(). Defination of setSessionId is as follows:

int Cli::setSessionId()
{
    SessionHandler oHandleSession;
    return oHandleSession.getSessionId(sSessionId);
}

now in order to mock functions of SessionHandler I have used macros to add virtual keyword before the functions I want to mock, in this case getSessionId()as this class is not abstract and functions are not pure virtual.(I know about Hi-Perf Dependency Injection but dont want to go in it at this stage)

Had the case been this

int Cli::setSessionId(SessionHandler* oHandleSession)
{
  ...
  return oHandleSession->getSessionId(sSessionId);
}

It would have been simple to just pass the mocked object to the function setSessionid() but since aggregation is used, how can I mock this function getSessionId()?


Solution

  • You can use static polymorphism or you can use link-time substitution.

    For static polymorphism you do something like this:

    class DefaultSessionHandler {
      // methods implemented as you do now
    };
    
    template <typename T>
    class SessionHandlerT {
      // methods implemented in terms of delegation to methods on T
    };
    
    using SessionHandler = SessionHandlerT<DefaultSessionHandler>; 
    

    This can be a little cumbersome and can introduce additional compile times and while it can be made to work, I'm not much of a fan of this approach, even though I've done it multiple times before.

    With link-time substitution, you provide an alternate implementation of SessionHandler and resolve the situation at link time. This means you have some other implementation of the SessionHandler class that does something different even though it has the same name. Again, this is cumbersome but can be made to work.

    Both of these methods have their own sets of problems and pain that they introduce. A better method of unit testing is to simply use dependency injection by refactoring the SUT.

    Another approach is to forego unit testing and only perform integration testing. This also has it's own set of problems.