1

我正在学习在现有的嵌入式 C 代码库(我可以调整以适应)上使用 Ceedling 和用于模拟的 CMock 进行单元测试。

我遇到过这样一种情况,一个单元中的一个函数调用同一单元中的第二个函数。

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. */
}

我不想测试foo_a()作为测试的一部分foo_b() 。我如何模拟foo_a()以便我仍然可以测试它是否被调用但不测试foo_a()函数本身?

4

2 回答 2

0

如果不修改源代码,您将无法做到这一点。

考虑将函数分解为两个单独的编译单元。

或者,#ifndef TEST在要替换的函数周围添加一个。

于 2016-11-08T11:59:34.020 回答
0

根据我使用 ceedling 的经验,最好的方法是创建自定义TEST_ASSERT_FOO_A_IS_CALLED();或细微差别。TEST_ASSERT_IS_DOING_WHAT_FOO_A_SHOULD_BE_DOING(); 在第二种情况下,您正在测试是否正在执行某些操作,而不是您不应该知道的内部功能。

理论上,使用单元测试你不关心这个函数是如何运行的(IE你不关心是否foo_b()调用foo_a(),只要foo_b()对模拟函数做同样的事情foo_a())并且你不应该能够判断一个内部(私有)函数是否这样所谓foo_a()的。因此,您应该测试是否正在调用模拟函数,而不是内部函数本身。

如何创建自定义 ASSERT?这很简单,只需使用普通的 C 宏定义它,例如:

#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!"); \
}

包含“_MESSAGE”断言不是必需的,但更容易发现宏中的哪个断言失败,因为宏中的每个“失败”都会显示相同的行号,因此更难发现它。

如果由于某种原因它发生了很多,这是一个签名,foo_a()应该在另一个可以模拟的源文件中。

于 2021-01-26T18:10:10.817 回答