Background
I am working on a project that interfaces with various cameras and their unique APIs. All cameras are abstracted into one interface, and the camera-specific API calls are contained within their own implementing classes.
Problem Explanation
I am trying to test a factory method that parses a form of configuration, and returns a pointer to the newly created camera. Here is a high-level view of what that looks like:
// camerafactory.cpp
Camera* make_camera(Config& config) {
switch (config.type) {
case CameraTypes.A : {
int paramInt = config.paramInt;
return new CameraA(paramInt);
}
case CameraTypes.B : {
string paramString = config.paramString;
return new CameraB(paramString);
}
case CameraTypes.C : {
float param1 = config.param1;
float param2 = config.param2;
return new CameraC(param1, param2);
}
default: {
throw std::invalid_argument("Invalid configuration!");
}
}
}
I want to test that these constructors are getting called correctly, however this would require the cameras to be physically connected to the computer to allow for the camera API's within the camera constructors to work. This does make sense for some testing situations, i.e. demonstrating hardware in the loop, however in my specific case, it is unrealistic to have all types of cameras connected at a single time.
I would like to test that these constructors are at least getting called with the correct parameters, demonstrating that the parsing is working correctly. I have considered abstracting out the parsing and testing that separately, but technically there is still the constructor call that is not being tested. I was also always told that adding functionality for the sake of testing is usually something that should be avoided, so that is another thing I am considering with my solution. It would also be interesting to find a solution that allows easy compile-time switching between mocks/concrete implementations to test hardware in the loop.
Versions
Note, I am using C++ 17, CMake, and the latest version of gtest.
Solutions being considered
Using macros to change the constructor calls to Mock constructor calls.
At the top of camerafactory.cpp
, adding something like:
// camerafactory.cpp
#ifndef PRODUCTION
#include "MockCamera.hpp"
#define CameraA MockCameraA
#define CameraB MockCameraB
#define CameraC MockCameraC
#endif
Where MockCameraN
are defined in a separate hpp/cpp file with identical constructors, and also implement the same Camera Interface, which I can then use to test correct construction.
This would allow me to test that the constructors are getting called correctly, but does feel like it goes against a cleaner solution that could be done with a language like Java.
Using GMock
I have not looked too deeply into it yet, but GMock seems to be promising: http://google.github.io/googletest/gmock_cook_book.html