2

想象一下,我们有一个单元测试,它首先执行一个我们希望函数someFunc不会被调用的代码序列,然后执行一个我们希望该函数只被调用一次的代码序列。使用HippoMocks,我们可以这样写:

#include <hippomocks.h>

void someFunc (void)
{

}

int main (int argc, char ** argv)
{
    MockRepository mocks;
    mocks.autoExpect = false;

    mocks.NeverCallFunc(someFunc); // line 27

    /* some testing code ... */

    /* ... in the course of which someFunc does not get called ... */

    mocks.ExpectCallFunc(someFunc); // line 33

    /* other testing code ... */
    someFunc();
    /* ... in the course of which someFunc got called */

    return 0;
}

但是,在 Windows 上运行上述代码片段(使用 Cygwin 工具链编译)时,HippoMocks::ExpectationException会抛出 a:

terminate called after throwing an instance of 'HippoMocks::ExpectationException'
what():  Function someFunc() called with mismatching expectation!
Expectations set:
../main.cpp(33) Expectation for someFunc() on the mock at 0x0 was not satisfied.
Functions explicitly expected to not be called:
../main.cpp(27) Result set for someFunc() on the mock at 0x0 was used.

所以我想知道...

... (1),如果 HippoMocks 不是为处理这种情况而设计的。期望someFunc被调用(第 33 行)不会取代相应模拟存储库中的先前期望吗?

...(2),为什么没有满足第二个期望(第 33 行),因为someFunc明确地被调用了。如果有的话,我会期望第一个期望(第 27 行)没有得到满足?

有趣的是,事情正好相反。以下代码段运行没有任何问题:

#include <hippomocks.h>

void someFunc (void)
{

}

int main (int argc, char ** argv)
{
    MockRepository mocks;
    mocks.autoExpect = false;

    mocks.ExpectCallFunc(someFunc); // line 27

    /* some testing code ... */
    someFunc();
    /* ... in the course of which someFunc got called */

    mocks.NeverCallFunc(someFunc); // line 33

    /* other testing code ... */

    /* ... in the course of which someFunc does not get called ... */

    /* someFunc(); */ 

    return 0;
}

此外,如果someFunc在第二个片段中的第二个期望后面插入了对的调用(如注释中所示),这将被检测到并报告为违反 HippoMocks 的“从不调用”期望,正如人们所期望的那样:

terminate called after throwing an instance of 'HippoMocks::ExpectationException'
  what():  Function someFunc() called with mismatching expectation!
Expectations set:
../main.cpp(27) Expectation for someFunc() on the mock at 0x0 was satisfied.
Functions explicitly expected to not be called:
../main.cpp(33) Result set for someFunc() on the mock at 0x0 was used.

HippoMocks 专家的任何帮助将不胜感激......

4

3 回答 3

3

和之间的交互之前NeverCallExpectCall没有真正考虑过——我从没想过人们会使用NeverCall很多东西,所以我没有意识到交互作用。

在当前发布的版本中,aNeverCall会自动期待上一个ExpectCall,并且NeverCall首先检查所有 s。这导致ExpectCall/NeverCall按预期工作 - 即,您首先获得预期,然后NeverCall是活动的。如果添加NeverCall/ ExpectCallno autoexpects 并且NeverCall获得优先级。这是违反直觉的,我认为最好交换行为,以便ExpectCalls 在可以匹配时始终获得优先权。

我已将您的示例添加为新的测试用例并交换了NeverCalland的匹配顺序ExpectCall。我还删除了autoExpectfor NeverCalls - 因为那本来就不应该存在。结果是您的两个示例现在都将以您期望的方式工作,autoExpect打开或关闭。如果在设置之后,您的第二个示例将起作用。这使您可以比以前更多地对设置代码进行分组。someCallNeverCall

如果你想测试/切换到这个版本,注意它还在 cpp11 分支上。当确认分支稳定且文档正确扩展时,我会将其合并到 master 和 release。目前没有已知问题。它在 Github 上:https ://github.com/dascandy/hippomocks/tree/cpp11 。

于 2017-02-06T13:05:35.980 回答
1

MockRepository在调用的析构函数或显式调用其VerifyAll()方法时检查 Hippomocks 期望。VerifyAll()在第 33 行之前调用,您的第一个示例应该可以正常工作。

我第二个回答是测试代码和测试代码不应该混淆,但我可以想象这只是为了一个紧凑的问题。

于 2016-09-09T11:56:13.153 回答
1

您不能这样做,因为 NeverCall 旨在为断言抛出异常。对我来说似乎完全不合逻辑。

如果您真的想解决这个问题,请设置以下内容

mocks.OnCallFunc(someFunc).Do(someFuncCalledHandler);

在您自己的处理程序中,您可以实现所需的逻辑:

bool callAllowed = true; //global variable
void someFuncCalledHandler()
{
    if (!callAllowed)
    {
        throw MyNeverCallException();
    }
}

在您的测试中,您可以控制 someFuncCalledHandler() 的行为:

callAllowed = false;
someFunc();

顺便说一句:正如您在示例代码中所做的那样,在测试中混合排列和操作代码是一个坏主意

于 2016-07-29T08:28:12.290 回答