简体   繁体   中英

Can a header with declared functions be mocked?

I'm working in a project targeting a Silicon Labs microcontroller. I want to create a wrapper for the Bluetooth SDK calls. SDK libraries are heavy on dependencies, so by creating a seem in that interface, I can avoid adding them to my tests. Note that this problem is not specific of the Silicon Labs platform, but I will leave the SiLabs SDK file names in case the reader is familiar with the platform.

I'm using CPPUTest as my testing framework. My code is a mix of C and C++, but for the purposes of this question, it's C.

For example, one of my wrapping functions (in a module called Bluetooth_HW ) would be

/* On "Bluetooth_HW.c" */

#include "native_gecko.h" // declares gecko_cmd_le_gap_bt5_set_adv_data()

// Set a new advertisement, either as advertisement packet or as a response.
bool BT_setAdvertisementMessage(uint8_t scanResponse, uint8_t adLength, uint8_t* newAdvertisement) {
    uint16_t result = gecko_cmd_le_gap_bt5_set_adv_data(0, scanResponse, adLength, newAdvertisement)->result;
    if (result != bg_err_success) {
        return false;
    } // Else, no errors setting the advertisement
    return true;
}

BT_setAdvertisementMessage() wraps gecko_cmd_le_gap_bt5_set_adv_data() , which is defined in native_gecko.h , an SDK header file. I declare BT_setAdvertisementMessage() in Bluetooth_HW.h and define it in bluetooth_HW.c . My code that needs to set the advertisement message then includes Bluetooth_HW.h instead of native_gecko.h , and Bluetooth_HW.h is easy to mock.

I would like to test Bluetooth_HW.c . I need to mock native_gecko.h for that, as I am not interested in running its code (it's provided by the manufacturer, I trust it, plus I'm not unit testing native_gecko , I'm unit testing Bluetooth_HW ). Normally, I would include the production .h file in my tests, to get declarations of the functions, and then substitute the .c file that contains the production code definitions with my fake implementation.

My problem is that native_gecko.h defines gecko_cmd_le_gap_bt5_set_adv_data() as an inline inside the header, instead of the more common approach of doing it on a .c file.

I could wrap native_gecko.h itself on a header that just declares the functions that I need, and make my code include that header, but then I don't have access to other stuff declared in native_gecko.h , like custom types and enums. I can't move those types and enums to the wrapper, as I can't remove them from native_gecko.h and the compiler would then complain of being defined twice, and I don't want to touch native_gecko.h , because it's an SDK file.

So, my question is how to mock modules that define code in their headers?

I managed to get it working by providing a fake native_gecko.h . The test environment is then pointer to the fake header instead of the production one. In my case, as native_gecko.h is massive, I just surgically added the minimum amount of elements required for it to work. I added just the declarations for the functions needed. Although I could have mimicked the behaviour of the real module and add them as inline functions, this would require including the mocking framework from CPPUTest to be included to native_gecko.h , which is C++. When the compiler tries to compile Bluetooth_HW.c as C code and pulls the header, it will complain about the presence of the C++ code. By adding the mocked function definitions to their own file, I could leave the mocking framework code out of the header, and my original, production code, C file would compile with just C code.

Roughly, the steps would be

  1. Make sure that the test project can't see the real, production code, native_gecko.h .
  2. Provide a fake version of it, substituting any defined functions for declarations (if the file is too big, as is the case of native_gecko.h , just create declarations for the functions used in your Code-Under-Test).
  3. Provide definitions for those functions.

Creating a fake header is not ideal, as the contents can change with an SDK update, for example, and there's room for human error, but it's the cleanest solution I could come up with.

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