C++ HippoMocks-使用;ExpectCallFunc";“之后”;NeverCallFunc“;对于相同的功能,会导致意外的;HippoMocks::ExpectationException“;
假设我们有一个单元测试,它首先执行一系列代码,我们希望函数C++ HippoMocks-使用;ExpectCallFunc";“之后”;NeverCallFunc“;对于相同的功能,会导致意外的;HippoMocks::ExpectationException“;,c++,unit-testing,hippomocks,C++,Unit Testing,Hippomocks,假设我们有一个单元测试,它首先执行一系列代码,我们希望函数someFunc不会被调用,然后执行一系列代码,我们希望函数只被调用一次。使用,我们可以这样写: #include <hippomocks.h> void someFunc (void) { } int main (int argc, char ** argv) { MockRepository mocks; mocks.autoExpect = false; mocks.NeverCallFu
someFunc
不会被调用,然后执行一系列代码,我们希望函数只被调用一次。使用,我们可以这样写:
#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;
}
所以我想知道
。。。(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;
}
如果您能得到HippoMocks专家的任何帮助,我们将不胜感激……您不能这样做,因为NeverCall的设计目的是为断言抛出异常。 对我来说似乎完全不合逻辑 如果您真的想避开这个问题,请设置以下内容
mocks.OnCallFunc(someFunc).Do(someFuncCalledHandler);
在您自己的处理程序中,您可以实现所需的逻辑:
bool callAllowed = true; //global variable
void someFuncCalledHandler()
{
if (!callAllowed)
{
throw MyNeverCallException();
}
}
在测试中,您可以控制someFuncCalledHandler()的行为:
顺便说一句:在测试中混淆排列代码和动作代码是一个坏主意,正如您在示例代码中所做的那样,Hippomock期望值在调用
MockRepository
的析构函数或显式调用其VerifyAll()
方法时被检查。在第33行之前调用VerifyAll()
,您的第一个示例将正常工作
我支持前面的答案,即测试代码和测试代码不应混淆,但我可以想象,这只是为了一个简洁的问题。以前没有真正考虑过
NeverCall
和ExpectCall
之间的交互-我从来没有期望人们使用NeverCall
太多,所以我没有意识到这两者之间的相互作用
在当前发布的版本中,NeverCall
将在先前的ExpectCall
上获得一个autoexpect,并且将首先检查所有NeverCall
s。这将导致ExpectCall
/NeverCall
按预期工作-即,您首先获得expect,然后NeverCall
处于活动状态。在NeverCall
/ExpectCall
noautoexpect
s的情况下,添加NeverCall
并获得优先级。这是违反直觉的,我认为最好交换行为,以便ExpectCall
s在匹配的情况下始终获得优先级
我已经将您的示例添加为一个新的测试用例&交换了NeverCall
和ExpectCall
的匹配顺序。我还删除了NeverCall
s的autoExpect
,因为它本来就不应该存在。结果是,您的两个示例现在都将以您期望的方式工作,autoExpect
打开或关闭。如果someCall
设置在NeverCall
之后,则第二个示例也可以使用。这允许您比以前更多地对设置代码进行分组
如果要测试/切换到此版本,请注意它仍然位于cpp11分支上。当分支被确认稳定并且文档被正确扩展时,我将把它合并到master&release。目前还没有已知的问题。它在Github上:.尽管它不能消除每次面对所描述的场景时向测试流中插入额外代码的需要,但手动调用
VerifyAll
似乎是一个可以容忍的解决方案-至少它可以避免通过Do
添加自己的转向行为实现的需要。。。但是,您建议使用的VerifyAll
对我不起作用(使用进行了测试)。仍然获得与最初描述相同的输出。您使用的是哪个版本的Hippomock?至于混合测试代码和测试代码,您完全正确:我的意图是尽可能使示例代码紧凑。我使用我们的Hippomock.h版本测试了原始代码和修改后的代码(如果我没记错的话,请使用版本4)。两者都很好。我用你提到的版本测试了这两个,并且都抛出了一个异常。恐怕我的答案不能回答您的问题,但很抱歉,我没有机会进一步分析差异。我同意测试代码和测试代码不应该混淆-这只是为了有一个紧凑的问题。但是,我不同意在相互作用中使用NeverCall
和ExpectCall
是没有意义的:除了在测试代码中强调在执行特定代码段时不得调用给定函数,而在执行另一段代码时应调用给定函数之外,通过NeverCall
明确说明这一点也可以在未满足所需约束的情况下(尤其是涉及函数参数的情况下)获得更清晰的信息。提供的解决方案是否有助于解决您的问题?好的,它解决了紧凑示例的问题。但想象一下,我们不仅期望在特定部分调用someFunc
,而且还希望通过Do
将someFunc
的工作委托给另一个函数,这在现实场景中很常见。另外,假设我们在原始用例中有多个函数。我认为事情很快就会变得混乱,所有的标志和手动从不调用处理程序。因此,我仍然希望找到一种不需要手动复制NeverCallFunc
约束功能的解决方案。。。
mocks.OnCallFunc(someFunc).Do(someFuncCalledHandler);
bool callAllowed = true; //global variable
void someFuncCalledHandler()
{
if (!callAllowed)
{
throw MyNeverCallException();
}
}
callAllowed = false;
someFunc();