简体   繁体   中英

Mock non-virtual methods using pre-processor

I am working on an embedded project in C++ where the resources are a bit limited. This means I try to be careful about using too many virtual methods unless I really need them. I am planning to start implementing unit-tests perhaps with Gtest.

Because the project is not too big in code size most of the code is written directly in the header file. The only penalty is a bit more compiling time. As it takes ~20 seconds to compile this is not an issue and in my opinion makes code easier to write/read.

If the project was running in Windows I would be all for creating new abstraction layers (or adding seam classes) and having more virtual methods where I need them for unit-testing. Because of the nature of the project I don't want to add extra virtual methods just for unit-testing purposes. I think it would be valid to do it but seems a bit unreasonable when the resources are scarce.

The project is running well and unit-testing is nice to have so I would like to keep code modifications to a minimum. One of the solutions to the problem is to do some trickery with the templates using "hi-perf dependency injection". This to me seems like duck typing and still requires modifying the original source code where the class is used.

I was thinking why not just use the pre-processor:

#ifdef TEST
#define TESTABLE virtual
#else
#define TESTABLE
#endif

Then when the time comes that a method needs to be mocked you could always modify the original source code for that class and write something like:

TESTABLE void somePreviouslyUnmockeableMethod(void);

I am aware one of the disadvantages is that I would have now two source codes, one for production and one for testing. The same happens anyway when one decides to use a Mock class instead of the real class when unit-testing. If the code changes were quite big the changes with the pre-processor could be a real problem but I think with this definition they are kept to a minimum.

Is this a valid solution? Are the some negative consequences I may be overlooking?

Note that all the modules already include a ProjectSettings.h file where the TESTABLE definition could be added with ease.

If making the classes virtual is really too costly (ie you measured that this would be too much overhead), you can use hi-perf dependency injection technique. The cost is then only i longer compilation time but no runtime overhead. In production you instantiate your class with real object and in tests - with a mock class that have methods with the same signatures as the real clas.

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