交织EXPECT_CALL()和对模拟函数的调用 [英] Interleaving EXPECT_CALL()s and calls to the mock functions

查看:935
本文介绍了交织EXPECT_CALL()和对模拟函数的调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Google Mock文档说:

重要说明::在调用模拟功能之前,必须先设置期望的Google Mock,否则行为未定义.特别是,您不得交错EXPECT_CALL()和对模拟函数的调用.

有人知道此限制的任何详细信息吗?我有许多单元测试肯定违反了该规则,但是似乎可以正常运行.

解决方案

我不同意 @Marko Popovic的评估 ,并相信他所做的只是碰巧可以正常工作的未定义行为. 我亲眼看到他在做什么,打了个电话,看起来还不错.但我认为这是不确定的行为.

不过,我需要Google明确说明,因此我在这里打开了此问题: https: //github.com/google/googletest/issues/2828 .请加快投票以引起关注,因为我希望Googletest小组自己对此予以澄清.

更新: Google已答复,并声明@Marko Popovic的答案取决于未定义的行为.但是,这是一个非常常见的陷阱,因为正如Marko所指出的,并且正如我所看到的,它确实有效(至少在大多数情况下如此).问题在于它依赖于未定义的gmock行为.

行为未定义的问题是它经常运行,但在技术上并不正确,可能有错误,可能导致不稳定的测试,并且在将来更新gmock时可能因未知原因而中断将来.简而言之:未定义的行为不能适应未来,也不能跨平台.这也可能导致比赛情况,或者并非始终有效.因此,请不要这样做.听听Google.他们声明以下内容的声明实际上是正确的:

尤其是,您不得插入EXPECT_CALL()和调用模拟函数( Google模拟-我可以在同一个模拟对象上多次调用EXPECT_CALL ?


[我自己写开始时的报价单]

问题3:我可以调用EXPECT_CALL来设置模拟方法的一些期望值,调用模拟方法,然后再次在该方法上调用EXPECT_CALL来更改期望值,然后再次调用模拟方法吗?

OP甚至没有明确地问这个问题,但是我找到此页面的唯一原因是因为我一直在寻找这个答案很多小时而找不到.我的Google搜索结果是"[[gmock multiple expect_call] [10]".因此,其他提出此问题的人也将落在此页面上,并且需要一个结论性的答案.

A:不,您不能这样做!根据Google的说法,尽管它可能看起来似乎可以在测试中起作用,但它会产生未定义的行为.请参阅上面的一般规则#2!

" 重要说明: gMock要求在调用模拟功能之前设置期望,否则行为未定义.特别是,您不得交错EXPECT_CALL()并调用模拟函数"( https://github .com/google/googletest/blob/master/googlemock/docs/for_dummies.md#using-mocks-in-tests )

因此,这是不允许的!

[我自己写的结尾的报价单]

更新(请参阅我的回答下方的评论):

也许这不是未定义的行为!?我添加的只是 Mock::VerifyAndClearExpectations(&myMockObj) .

TEST(FooTest, testCaseName)
{
    MyMock myMockObj;
    ...
    EXPECT_CALL(myMockObj, myMethod(_)).WillOnce(Return(true));
    testMethod();
    ASSERT_THAT(...);

    Mock::VerifyAndClearExpectations(&myMockObj); // <== NOTICE THIS ADDED LINE!
    EXPECT_CALL(myMockObj, myMethod(_)).WillOnce(Return(false));
    testMethod();
    ASSERT_THAT(...);
}

参考:

  1. @Marko Popovic的评估
  2. 我要求澄清以下问题的Googletest问题: https://github.com/google /googletest/issues/2828
  3. [我自己的答案] Google Mock documentation says:

    Important note: Google Mock requires expectations to be set before the mock functions are called, otherwise the behavior is undefined. In particular, you mustn't interleave EXPECT_CALL()s and calls to the mock functions.

    Does anyone know any details behind this restriction? I have a number of unit tests which definitely violate this rule but seem to function properly, however.

    解决方案

    I have to disagree with @Marko Popovic's assessment, and believe what he's done is undefined behavior that happens to work. I have personally seen what he is doing, interleaving calls, to appear to work just fine. But I think it's undefined behavior.

    Nevertheless, I need clarity from Google, so I've opened this issue here: https://github.com/google/googletest/issues/2828. Please go upvote it to get it attention, as I'd like the Googletest team to clarify this themselves.

    Update: Google has responded, and declared that @Marko Popovic's answer relies on undefined behavior. It is a very common trap to fall in, however, because, as Marko has pointed out, and as I have seen too, it does indeed work (most of the time at least). The problem is that it is relying on undefined gmock behavior.

    The problem with undefined behavior is it works oftentimes, but isn't technically correct, may be buggy, can lead to flaky tests, and can break for unknown reasons in the future when gmock gets updated in the future. In short: undefined behavior is not future-proof and not cross-platform. It may also result in race conditions or otherwise not always work. Therefore, don't do it. Listen to Google. Their statement where they state the following is in fact correct:

    In particular, you mustn't interleave EXPECT_CALL()s and calls to the mock functions (https://github.com/google/googletest/blob/master/googlemock/docs/for_dummies.md#using-mocks-in-tests)


    Back to my original answer:

    In this other answer of mine where I talk a lot about how to properly use multiple EXPECT_CALL()s, I state interleaving is not okay: google mock - can I call EXPECT_CALL multiple times on same mock object?


    [QUOTE FROM MY OWN WRITING START]

    Question 3: Can I call EXPECT_CALL to set some expectations on a mock method, call the mock method, then call EXPECT_CALL on the method again to change the expectations, then call the mock method again?

    This question wasn't even explicitly asked by the OP, but the only reason I found this page is because I was searching for this answer for many hours and couldn't find it. My Google search was "[gmock multiple expect_call][10]." Therefore, others asking this question will also fall on this page and need a conclusive answer.

    A: NO, you can NOT do this! Although it may seem to work in testing, according to Google, it produces undefined behavior. See general rule #2 above!

    "Important note: gMock requires expectations to be set before the mock functions are called, otherwise the behavior is undefined. In particular, you mustn't interleave EXPECT_CALL()s and calls to the mock functions" (https://github.com/google/googletest/blob/master/googlemock/docs/for_dummies.md#using-mocks-in-tests)

    Therefore, this is NOT ALLOWED!

    [QUOTE FROM MY OWN WRITING END]

    Update (see the comments below my answer):

    Perhaps this is NOT undefined behavior though!? All I added was Mock::VerifyAndClearExpectations(&myMockObj).

    TEST(FooTest, testCaseName)
    {
        MyMock myMockObj;
        ...
        EXPECT_CALL(myMockObj, myMethod(_)).WillOnce(Return(true));
        testMethod();
        ASSERT_THAT(...);
    
        Mock::VerifyAndClearExpectations(&myMockObj); // <== NOTICE THIS ADDED LINE!
        EXPECT_CALL(myMockObj, myMethod(_)).WillOnce(Return(false));
        testMethod();
        ASSERT_THAT(...);
    }
    

    References:

    1. @Marko Popovic's assessment
    2. Googletest issue where I ask for clarity about this: https://github.com/google/googletest/issues/2828
    3. [my own answer] google mock - can I call EXPECT_CALL multiple times on same mock object?

    这篇关于交织EXPECT_CALL()和对模拟函数的调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆