【问题标题】:Passing arbitrary arguments to invocked methods with Google C++ Mocking Framework (Google Mock) (V1.5)使用 Google C++ Mocking Framework (Google Mock) (V1.5) 将任意参数传递给调用的方法
【发布时间】:2015-03-13 20:34:09
【问题描述】:

我有一个模拟方法。当它被调用时,我希望它在调用它的正常行为之前调用另一个函数。类似的东西:

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        Invoke(my_obj, &SomeAdditionalMethodIWantToCall),
        Invoke(my_obj, &DefaultBehavior),
        ));

唯一的问题是SomeAdditionalMethodIWantToCall 期望的参数与提供给MockedMethod 的参数完全不相关。我希望能够提供它们,但我在语法上苦苦挣扎。我希望有类似的东西(假语法):

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        Invoke(my_obj, &SomeAdditionalMethodIWantToCall, arg1, arg2, arg3),
        Invoke(my_obj, &DefaultBehavior),
        ));

我在文档中寻找过这样的东西,但没有成功。

Using a Function or a Functor as an Action,我们有:

  • Invoke(f)Invoke(object_pointer, &class::method)InvokeWithoutArgs(f)InvokeWithoutArgs(object_pointer, &class::method) 在调用模拟函数时只会转发(或不转发)提供给模拟函数的参数。

  • InvokeArgument<N>(arg1, arg2, ..., argk)似乎是为了调用参数之一。

Composite Actions

  • WithArg<N>(a)WithArgs<N1, N2, ..., Nk>(a) 似乎是选择从原始函数中转发哪些参数。

我想我遗漏了一些非常明显的东西,但我有点卡在这里,所以任何建议都会有所帮助。

【问题讨论】:

    标签: c++ unit-testing parameters mocking googlemock


    【解决方案1】:

    如果你使用的是 c++11,你可以像这样使用 lambda 函数:

    EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        InvokeWithoutArgs([&]() { 
            my_obj->SomeAdditionalMethodIWantToCall(arg1, arg2, arg3); 
        },
        Invoke(my_obj, &DefaultBehavior)   
    ));
    

    【讨论】:

    • 非常优雅!谢谢。
    • 什么是私有方法?
    【解决方案2】:

    一种可能的选择是使用Assign 操作将参数的值保存到类变量中,然后使用帮助程序调用另一个函数。使用以下期望:

    EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
        .WillOnce(DoAll(
            Assign(&classVariable1, arg1),
            Assign(&classVariable2, arg2),
            Assign(&classVariable3, arg3),
            InvokeWithoutArgs(my_obj, &MyClass::SomeAdditionalMethodIWantToCallHelper),
            Invoke(my_obj, &MyClass::DefaultBehavior),
            ));
    

    然后定义你的辅助函数如下:

    void MyClass::SomeAdditionalMethodIWantToCallHelper()
    {
        SomeAdditionalMethodIWantToCall(classVariable1, classVariable2, classVariable3);
    }
    

    编辑

    另一个可能的选择是编写一个自定义操作,该操作接受一个指向成员函数的指针以及您希望传递给它的参数。这更接近您最初想要的语法。这是自定义操作:

    ACTION_P5(InvokeUnrelatedFunction, classPointer, pointerToMemberFunc,
              first, second, third)
    {
        (classPointer->*pointerToMemberFunc)(first, second, third);
    }
    

    以下是您在期望中使用它的方式:

    EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
        .WillOnce(DoAll(
            InvokeUnrelatedFunction(my_obj, &MyClass::SomeAdditionalMethodIWantToCall,
                                    arg1, arg2, arg3),
            Invoke(my_obj, &MyClass::DefaultBehavior),
            ));
    

    【讨论】:

    • 使用InvokeUnrelatedFunction 操作,我得到的只是一个编译器错误,说arg1 在我尝试调用该操作时没有声明。可能是什么原因造成的?
    • @Martin 如问题所述,arg1 是一个“与提供给MockedMethod 的参数完全不相关的参数”。如果你想将参数从MockedMethod 传递给一个函数,你可以使用Invoke。如果您愿意,也可以将InvokeWithArgs 结合使用。有关示例,请参阅 Google Mock Cookbook。
    • 我的编译器说需要一些返回值
    • @ChristopherPisz 您可能需要添加Return 子句。例如:EXPECT_CALL(...).WillOnce(DoAll(Invoke(...),Return(someValue)));
    • 是的,返回值用于模拟方法。但是,我需要在模拟方法返回之后进行调用。 :/ 我没有办法。
    猜你喜欢
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    相关资源
    最近更新 更多