Closed cakira closed 1 year ago
hey man. gMock has two major drawbacks:
The second can be workarounded somehow, but the first is a big issue.
Gracias, @fgr-17 . So gMock isn't a good option to my projects.
As a proof of concept about using fff with C++, I put the following macros in one of my C++ file:
#define FAKE_VOID_CLASS_FUNC0(classname, funcname) \
FAKE_VOID_FUNC(classname##__##funcname); \
void classname::funcname() { return classname##__##funcname(); }
#define FAKE_VALUE_CLASS_FUNC0(rettype, classname, funcname) \
FAKE_VALUE_FUNC(rettype, classname##__##funcname); \
rettype classname::funcname() { return classname##__##funcname(); }
#define FAKE_VALUE_CLASS_FUNC1(rettype, classname, funcname, arg0type) \
FAKE_VALUE_FUNC(rettype, classname##__##funcname, arg0type); \
rettype classname::funcname(arg0type arg0) { \
return classname##__##funcname(arg0); \
}
And they worked as intended in my code, because I could use:
FAKE_VOID_CLASS_FUNC0(BLEAdvertising, start);
FAKE_VALUE_CLASS_FUNC0(BLEServer *, BLEDevice, createServer);
FAKE_VALUE_CLASS_FUNC1(BLEService *, BLEServer, createService, const char *);
Instead of:
FAKE_VOID_FUNC(BLEAdvertising__start);
FAKE_VALUE_FUNC(BLEServer *, BLEDevice__createServer);
FAKE_VALUE_FUNC(BLEService *, BLEServer__createService, const char *);
void BLEAdvertising::start() { return BLEAdvertising__start(); };
BLEServer *BLEDevice::createServer() { return BLEDevice__createServer(); }
BLEService *BLEServer::createService(const char *uuid) {
return BLEServer__createService(uuid);
}
Limitation:
It didn't work to mock up void BLEDevice::init(std::string deviceName)
because when I tried to call FAKE_VOID_FUNC(BLEDevice__init, std::string)
, the compiler generated the warning below
warning: ‘void* memset(void*, int, size_t)’ clearing an object of type ‘BLEDevice__init_Fake’ {aka ‘struct BLEDevice__init_Fake’} with no trivial copy-assignment; use assignment or value-initialization instead [-Wclass-memaccess]
Understandably, one cannot apply memset() in a std::string variable.
FFF is not the right tool for mocking C++ code because of name-mangling.
You should be using a C++ mocking framework:
it has no support for single functions (outside a class) it requires member class to be declared as virtuals.
That's because both cases are usually a sign that your architecture isn't quite right. You can't use run-time polymorphism unless your your methods are declared as virtual
. Using stand-alone functions means that you're abandoning OOP. If you're following the general software engineering practices, you won't have stand-alone functions and your concrete classes will be implementations of an interface class (they'll use override
). C++ doesn't have an official designation for interfaces like C# does.
I understand that the paragraph above isn't always true for deeply embedded projects. I'll way that C++ isn't a good fit to those because C++ binaries tend to be larger, especially if you use templates extensively. You're probably better off using C with a well-designed architecture (in that case FFF will fit like a glove).
If your CPU has a MMU and lots of memory, you should be adhering to SW engineering practices and GTest's limitations won't be an issue.
If you have to use C++ and you can not use virtual functions, you can always create your own stubs, like in @cakira examples. I'd never hack the FFF header, I'd just wrap them on C++ stubs.
Almost two years have passed since I opened this ticket, and now I tend to think that I was trying to do too much with fff.
The truth is, I attempted to learn CppUMock and Google Mock, but for some reason, I find them less intuitive compared to ThrowTheSwitch/Unity + meekrosoft/fff. As a result, I ended up trying "to use a nail as a screw".
I'll try harder to learn CppUMock or a similar tool and leave Unity + fff for pure C projects.
As a last tidbit, I use Google Test + FFF to test C code. I find that much, much better than ThrowTheSwitch/Unity. I get an excellent test harness framework while still being able to mock C code with FFF. Just note that the code under test is C, not C++. When I have to test C++ code, I use GTest + GMock.
Is there anyone using fff to mock class member functions?
I'm running unit tests in a code for the Arduino framework, which use C++ objects. In order to make to code compile, right now I declared some stubs, for instance:
File test_ble_manager.cpp
But I would like to do something like: File test_ble_manager.cpp (this is an untested code)
So I could use
BLECharacCB_onWrite_fake.call_count
and other features.My doubts are:
FAKE_CLASS_VOID_FUNC(BLECharacteristicCallbacks, onRead, BLECharacteristic *);
that would generate aBLECharacteristicCallbacks__onRead_fake.call_count
?