想象一下,我们有一个单元测试,它首先执行一系列代码,我们希望函数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专家的任何帮助都将不胜感激......
答案 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)
NeverCall
和ExpectCall
之间的互动之前并未真正考虑过 - 我从没想过人们会根本使用NeverCall
,所以我没有意识到这种相互作用。
在当前发布的版本中,NeverCall
将在之前的ExpectCall
上获得自动期望,并且将首先检查所有NeverCall
。这导致ExpectCall
/ NeverCall
按预期工作 - 即,您首先获得期望,然后NeverCall
处于活动状态。如果NeverCall
/ ExpectCall
添加了autoexpect
,则NeverCall
获得优先权。这是违反直觉的,我认为交换行为会更好,这样ExpectCall
总是可以获得优先权。
我已将您的示例添加为新的测试用例&amp;交换了NeverCall
和ExpectCall
的匹配顺序。我还删除了autoExpect
的{{1}} - 因为那不应该在那里出现。结果是,您的两个示例现在都将以您期望的方式工作,NeverCall
打开或关闭。如果autoExpect
在someCall
设置之后,您的第二个示例也有效。这使您可以比以前更多地对设置代码进行分组。
如果要测试/切换到此版本,请注意它仍在cpp11分支上。我将把它合并到master&amp;当分支被确认稳定时释放文档适当扩展。目前没有已知的问题。它在Github上:https://github.com/dascandy/hippomocks/tree/cpp11。