Search code examples
cstm32uart

Mocking/Stubbing HAL_UART_Receive() for the STM32


How do I mock/stub HAL_UART_Receive(&huart5, &temp, 1, BLUETOOTH_RX_TIMEOUT) for the stm32 using the CMock and unity framework?


Solution

  • To mock the UART driver, you should add something like this to your unit test source file. This is an example for an STM32L4 MCU, so the filename might be different if you are using a different variant.

    #include "mock_stm32l4xx_hal_uart.h"
    

    Then you can mock HAL_UART_Receive() with things like:

    HAL_UART_Receive_ExpectAndReturn(&huart5, &temp, 1, BLUETOOTH_RX_TIMEOUT, HAL_OK);
    

    Or you could stub it with something like:

    HAL_UART_Receive_AddCallback(your_stub_function);
    

    So imagine that you had some function that you wanted to test like this:

    foo.c

    int some_function(void)
    {
        int result;
    
        if (HAL_UART_Receive(&huart5, &temp, 1, BLUETOOTH_RX_TIMEOUT) == HAL_OK)
            result = 0;
        else
            result = 1;
    
        return result;
    }
    

    You might test it like so:

    test_foo.c

    #include "unity.h"
    #include "mock_stm32l4xx_hal_uart.h"
    
    void test_some_function_success(void)
    {
        uint8_t dummy_buffer[1];
    
        // We expect HAL_UART_Receive() to be called with these arguments
        // If it is called, we will mock it and return HAL_OK to the code under test
        HAL_UART_Receive_ExpectAndReturn(&huart5, dummy_buffer, 1, BLUETOOTH_RX_TIMEOUT, HAL_OK);
    
        // However, we don't care what the pData argument is
        HAL_UART_Receive_IgnoreArg_pData();
    
        // Now call the function to test.
        // If it doesn't call HAL_UART_Receive() the test will fail
        int result = some_function();
    
        // Our function should return 0 since the result was HAL_OK
        TEST_ASSERT_EQUAL(0, result);
    }
    
    void test_some_function_fails(void)
    {
        uint8_t dummy_buffer[1];
    
        // We expect HAL_UART_Receive() to be called with these arguments
        // If it is called, we will mock it and return HAL_ERROR to the code under test
        HAL_UART_Receive_ExpectAndReturn(&huart5, dummy_buffer, 1, BLUETOOTH_RX_TIMEOUT, HAL_ERROR);
    
        // However, we don't care what the pData argument is
        HAL_UART_Receive_IgnoreArg_pData();
    
        // Now call the function to test.
        // If it doesn't call HAL_UART_Receive() the test will fail
        int result = some_function();
    
        // Our function should return 1 since the HAL function failed
        TEST_ASSERT_EQUAL(1, result);
    }