HippoMocks - 在“NeverCallFunc”之后使用“ExpectCallFunc”执行相同的功能会导致意外的“HippoMocks :: ExpectationException”

时间:2016-06-25 23:17:02

标签: c++ unit-testing hippomocks

想象一下,我们有一个单元测试,它首先执行一系列代码,我们希望函数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

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专家的任何帮助都将不胜感激......

3 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

callAllowed = false;
someFunc();

顺便说一下:在测试中混合排列和动作代码是个坏主意,就像你在示例代码中所做的那样

答案 1 :(得分:1)

在调用MockRepository的析构函数或明确调用其VerifyAll()方法时,会检查Hippomocks期望值。在第33行之前调用VerifyAll(),您的第一个示例将正常工作。

我先回答上一个答案,即测试代码和测试代码不应该混淆,但我可以想象它只是为了一个紧凑的问题。

答案 2 :(得分:1)

NeverCallExpectCall之间的互动之前并未真正考虑过 - 我从没想过人们会根本使用NeverCall,所以我没有意识到这种相互作用。

在当前发布的版本中,NeverCall将在之前的ExpectCall上获得自动期望,并且将首先检查所有NeverCall。这导致ExpectCall / NeverCall按预期工作 - 即,您首先获得期望,然后NeverCall处于活动状态。如果NeverCall / ExpectCall添加了autoexpect,则NeverCall获得优先权。这是违反直觉的,我认为交换行为会更好,这样ExpectCall总是可以获得优先权。

我已将您的示例添加为新的测试用例&amp;交换了NeverCallExpectCall的匹配顺序。我还删除了autoExpect的{​​{1}} - 因为那不应该在那里出现。结果是,您的两个示例现在都将以您期望的方式工作,NeverCall打开或关闭。如果autoExpectsomeCall设置之后,您的第二个示例有效。这使您可以比以前更多地对设置代码进行分组。

如果要测试/切换到此版本,请注意它仍在cpp11分支上。我将把它合并到master&amp;当分支被确认稳定时释放文档适当扩展。目前没有已知的问题。它在Github上:https://github.com/dascandy/hippomocks/tree/cpp11