Toby
Toby

Reputation: 10144

How to mock function in same UUT in C

I am learning unit testing using Ceedling, with CMock for mocks, on an existing, embedded C code-base (which I can adjust to suit).

I have come across the situation where one function in a unit calls a second function within the same unit.

int foo_a(int r) 
{
    /* foo_a work */
    /* do not wish to test this function just to test foo_b. */
}

int foo_b(int i) /* function to test */
{
    /* foo_b work */
    if (some_condition)
        foo_a(k); /* need to test if foo_a() is called or not. */
}

I don't want to test the foo_a() as part of the foo_b() tests. How do I mock foo_a() so that I can still test if it is called or not but without testing the foo_a() function itself?

Upvotes: 1

Views: 2565

Answers (2)

João PGC
João PGC

Reputation: 31

On my experience using ceedling, the best way is to create a custom TEST_ASSERT_FOO_A_IS_CALLED(); or , subtle difference, TEST_ASSERT_IS_DOING_WHAT_FOO_A_SHOULD_BE_DOING(); In the second case, you are testing if some set of action is being executed, not an internal function that you should not be aware of.

In theory, using unit tests you do not care how that function operates (I.E. you do not care if foo_b() calls foo_a(), as long foo_b() does the same things to mocked function as foo_a() ) and you SHOULD not be able to tell if an internal(private) function such as foo_a() is called. Therefore, you should be testing if the mocked functions are being called, not the internal function per se.

How to create a custom ASSERT? it is simple, just define it using normal C macros, example:

#define TEST_ASSERT_FOO_A_IS_CALLED() \
{                                     \
  TEST_ASSERT_CALLED(some_mocked_function_foo_a_is_expected_to_call);                              \
  TEST_ASSERT_EQUAL_MESSAGE(expected_value, some_mocked_function_foo_a_is_expected_to_call_fake.arg0_val, "Something wrong with arg0!"); \
}

Including the "_MESSAGE" asserts is not necessary but it is easier to spot which of the asserts inside the macro failed, since every 'fail' inside the macro will show the same line number, making more difficult to spot it.

If for some reason it is happening a lot, this is a signed that foo_a() should be in another source file that can be mocked.

Upvotes: 0

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137438

You can't do this without modifying your source code.

Consider breaking the functions out into two separate compilation units.

Or, add an #ifndef TEST around the function you want to replace.

Upvotes: 0

Related Questions