ThrowTheSwitch / CMock

CMock - Mock/stub generator for C
http://throwtheswitch.org
MIT License
684 stars 276 forks source link

Numcalls in Stubbed functions not reset from test to test #445

Closed ivankvolik closed 1 year ago

ivankvolik commented 1 year ago

Heelo, I have one question regarding the _Stub functions and cmock_num_calls. I am stubbing the same functions in two different tests. I have observed that cmock_num_calls is carried over from one test to the other. In test 1 it goes from 0-2, as i call the stubbed function three times.

When A call the stub again in the test 2 the numcalls is 3, which is not what I would have expected. Is this a planned behaviour and is there an option to reset cmock_num_calls between the tests for all stubs?

Thanks, Ivan.

mvandervoord commented 1 year ago

I suspect you've rolled your own test runners instead of using Ceedling or the test runner generator. You're forgetting to call the Validate function for each mocked module at the end of each test. This is necessary to both verify that all your expectations have been met, as well as reset everything for the next test.

ivankvolik commented 1 year ago

Hello Mark, thanks for the reply. You are right I am using make to build the whole thing, but the solution uses the generate_test_runner.rb and it is the default implementation. Now, I have looked into the generated runner source files and I can see CMock_Verify function. Is this what you were reffering to?

If so, the functions are called but they are generated as empty. This is what the runner file looks like:

/* AUTOGENERATED FILE. DO NOT EDIT. */

/*=======Automagically Detected Files To Include=====*/
#include "unity.h"
#include "testonia.h"
#include "dependency_mock.h"

/*=======External Functions This Runner Calls=====*/
extern void setUp(void);
extern void tearDown(void);
extern void test1(void);
extern void test2(void);
extern void test3(void);
extern void test4(void);
extern void test5(void);

/*=======Mock Management=====*/
static void CMock_Init(void)
{
}
static void CMock_Verify(void)
{
}
static void CMock_Destroy(void)
{
}

/*=======Test Reset Options=====*/
void resetTest(void);
void resetTest(void)
{
  tearDown();
  CMock_Verify();
  CMock_Destroy();
  CMock_Init();
  setUp();
}
void verifyTest(void);
void verifyTest(void)
{
  CMock_Verify();
}

/*=======Test Runner Used To Run Each Test=====*/
static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)
{
    Unity.CurrentTestName = name;
    Unity.CurrentTestLineNumber = line_num;
#ifdef UNITY_USE_COMMAND_LINE_ARGS
    if (!UnityTestMatches())
        return;
#endif
    Unity.NumberOfTests++;
    UNITY_CLR_DETAILS();
    UNITY_EXEC_TIME_START();
    CMock_Init();
    if (TEST_PROTECT())
    {
        setUp();
        func();
    }
    if (TEST_PROTECT())
    {
        tearDown();
        CMock_Verify();
    }
    CMock_Destroy();
    UNITY_EXEC_TIME_STOP();
    UnityConcludeTest();
}

/*=======MAIN=====*/
int main(void)
{
  UnityBegin("src/test/testonia_test.c");
  run_test(test1, "test1", 110);
  run_test(test2, "test2", 135);
  run_test(test3, "test3", 167);
  run_test(test4, "test4", 209);
  run_test(test5, "test5", 246);

  return UnityEnd();
}

Did I miss any parameters to generate_test_runner, or some call order?

mvandervoord commented 1 year ago

It appears the generated mock didn't notice that you have any mocks. It should be filling out the CMock_Verify function with a specific verify function for each mock module being included.

It needs two things to complete this task. First, you need to be including those mocks in your test file, like so:

include "mock_blah.h"

Second, the generator needs to know what mock prefix you're using. You can do this by giving the test runner generator the same config file you pass to cmock. Maybe something like this:

ruby generate_test_runner.rb cmock.yml testonia_test.c

My next guess is you're missing one of those two steps? :)

ivankvolik commented 1 year ago

It was the evil yml. Thanks a lot!