expect_call, how to invoke callback function with argument rvalue reference?

Viewed 1179

class A is under test, I want EXPECT_CALL to to return immediately, and invoke lamda function with value 200(rvalue reference) for mocked asyncfunc() method. Please read the comments in line with the code

#include "gtest/gtest.h"  
#include "gmock/gmock.h"  

#include<iostream>  
using namespace std; 

// Concrete class  
class B  
{   
    public:  
       // asyncfunc signature, p2 is function pointer with argument as rvalue referrence  
        bool asyncfunc(int p1, std::function<void(int &&v)> &&p2, float p3){  
            cout << "asyncfunc() \n" << "param1 : " << p1 << "\nparam 3 : " << p3 << endl;  
            p2(100);  
        }   
  
};  

class MockB  
{
    public:  
        // asyncfunc mocked  
        MOCK_METHOD3(asyncfunc, bool (int, std::function<void(int &&v)> &&, float));  
};  
  
// unit under test - A  
template< typename T>  
class A  
{
    T *bobj;  
    void sync(){}  
    public:  
    A(T *pbobj):bobj(pbobj){}    
    void test_function()  
    {
        bool value = bobj->asyncfunc(10, [this](int &&a){  
                    cout << "Lamba : " << a << endl;  
                    if(a == 100)  
                    {  
                      sync();  
                    }  
                },  
                20);  
        cout << "test_function : " << value << endl;  
    }  
};   

// My tests look like below, I get compilation error

TEST(A, test_function)  
{  
    MockB b;
    A<MockB> obj(&b);
    using namespace ::testing;   

    EXPECT_CALL(b, asyncfunc(_,_,_)).WillOnce(DoAll(InvokeArgument<1>(100),Return(true)));  
    obj.test_function();  
}
   
1 Answers

I'm not 100% sure as you code snippet doesn't specify if the lambda returns something or not - please follow 'minimal, reproducible example' principle, but I think the problem might be that lambda returns no type (void) and your mock function asyncfunc returns non-void type (e.g. bool). In this case, you need to specify what shall be returned by the call to asyncfunc by using Return action:

struct MockClass {
    MOCK_METHOD3(asyncfunc, bool(bool, std::function<void(bool)>, int));
};

TEST(MockTest, CallLambda) {
    MockClass m{};

    auto param{false};

    EXPECT_CALL(m, asyncfunc(_, _, _)).WillOnce(DoAll(InvokeArgument<1>(param), Return(false)));

    ASSERT_FALSE(m.asyncfunc(
        true, [](bool) {}, 42)); // ASSERT_FALSE because `Return` action specified `false`
}

without DoAll and Return actions, gmock tries to use result of InvokeArgument as the return value of asyncfunc which it can't, because it cannot use void as bool.

Related