【问题标题】:Checking if function, tested with CMockery, calls another particular function检查用 CMockery 测试的函数是否调用另一个特定函数
【发布时间】:2017-12-27 15:19:39
【问题描述】:

我在使用 CMockery 为如下所示的函数编写模拟代码时遇到问题。你能给我一些提示吗?我想测试是否调用了startCalCompute,并将值分配给updateMode,使其不等于SYSTEM_CAL_CONFIG。我需要的只是一个起点或提示。

foo.c

static void checkSystem(void)
{
#ifndef CAL
    startCalCompute();
#endif

    if( SYSTEM_CAL_CONFIG != updateMode )
    {
        updateLogevent(); 
    }

    ...
}

testfoo.c

void Test_checkSystem( void ** state )
{   
    // what to do here to check if startCalCompute() is called ?
}

【问题讨论】:

  • 如果?还有什么? will_return 是什么?
  • 我不确定 CMockery 能否在这里为您提供帮助;看起来您正在直接测试 checkSystem() 函数,而不是模拟它的依赖项。您可以独立检测到功能的任何影响(包括副作用)吗?

标签: c cmockery


【解决方案1】:

我想给updateMode赋值,使它不等于SYSTEM_CAL_CONFIG

如果updateMode 依赖于从另一个函数获得的值并且您想在测试期间控制它,那么您应该创建该函数的测试替身。 Here is a good answer explaining mocks in particular.如果完全是在checkSystem里面计算出来的,那么测试驱动不要修改它,因为它的目的只是为了检查整体结果。

checkSystem.c

/* checkSystem depends on a value returned by this function */
int getUpdateMode (void);

/* This function knows nothing about testing. It just does
   whatever it was created to do. */
void checkSystem (void)
{
    int updateMode = getUpdateMode ();
    if (SYSTEM_CAL_CONFIG != updateMode)
    {
        ...
    }
}

test_checkSystem.c

/* When testing checkSystem, this function
   will be called instead of getUpdateMode */
int mock_getUpdateMode (void);
{
    /* Get a value from test driver */
    int updateMode = (int) mock();

    /* Return it to the tested function */
    return updateMode;
}

void test_checkSystem_caseUpdateMode_42 (void ** state)
{
    int updateMode = 42;       /* Pass a value to mock_getUpdateMode */
    will_return (mock_getUpdateMode, updateMode);

    checkSystem ();            /* Call the tested function */
    assert_int_equal (...);    /* Compare received result to expected */
}

我想测试startCalCompute是否被调用

如果startCalCompute() 被有条件地编译为由checkSystem() 调用,那么您可以有条件地编译您想要在测试中完成的任何事情:

void startCalCompute (void);
void checkSystem(void)
{
#ifdef CAL
    startCalCompute();
#endif
}

void test_checkSystem (void ** state)
{
#ifdef CAL
    ...
#endif
}

如果您需要确保调用特定函数并且取决于运行时条件,或者如果某些函数以特定顺序调用,CMockery 中没有工具可以执行此操作。然而,CMocka 中的there are 是 CMockery 的一个分支,非常相似。以下是您在 CMocka 中的操作方式:

checkSystem.c

void startCalCompute (void);
void checkSystem (void)
{
    if (...)
        startCalCompute ();
}

test_checkSystem.c

/* When testing checkSystem, this function
   will be called instead of startCalCompute */
void __wrap_startCalCompute (void)
{
    /* Register the function call */
    function_called ();
}

void test_checkSystem (void ** status)
{
    expect_function_call (__wrap_startCalCompute);
    checkSystem ();
}

现在如果checkSystem 不调用startCalCompute,测试将像这样失败:

[==========] Running 1 test(s).
[ RUN      ] test_checkSystem
[  ERROR   ] --- __wrap_startCalCompute function was expected to be called but was not.
test_checkSystem.c:1: note: remaining item was declared here

[  FAILED  ] test_checkSystem
[==========] 1 test(s) run.
[  PASSED  ] 0 test(s).
[  FAILED  ] 1 test(s), listed below:
[  FAILED  ] test_checkSystem

【讨论】:

  • 感谢队友,这很有帮助。只有一个疑问 assert_int_equal (...); /* 将收到的结果与预期的结果进行比较 */ 我需要在这里比较的内容。一个值是我从模拟函数收到的 updateMode。其他值是什么?由于 checkSystem 返回 void 我将如何从该函数内部比较 updateMode?​​span>
  • @samprat 好吧,如果您只想检查您的函数是否调用了另一个函数,那么您不需要此断言。但通常,如果您测试一个函数,您希望确保它产生正确的结果,而不仅仅是调用另一个函数。如果checkSystem 将返回或更改变量,那么您将检查它是否正确。
  • @samprat 我建议您查看 cmocka 手册,而不是您从 Google 获得的 cmockery 手册。它们更清晰、更容易理解,并且您可以在cmockery 中以完全相同的方式执行大多数操作,因为这两个框架共享相同的代码库。毕竟,也许你甚至不需要一个单元测试框架来达到你的目的。
  • 非常感谢谢尔盖 B 的帮助。
猜你喜欢
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
相关资源
最近更新 更多