Write Async Test Case by gtest & gmock for C++

Recently, I have a project that needs some async IO function,  which use libuv as backend, and move the original logic in an async way.

The project was ok, but after I have good experience write node.js & Ruby on Rails code, I cannot live without test case for such a complex code.

Thankfully, deal stackoverflow.com give me the answer, which is gtest + gmock.

Let first have some taste about the code.

see the code in this link : gist.

(for security reason, I have ignore some logic part of this code, so it's cannot compile).

class: AsyncIOHttpCallback {} <- This is the callback class, you should define your callback interface in a virtual class, can be impl the policy by caller.

class: MockCallback which publicly inherit AsyncIOHttpCallback class, and  implement this class  member function by:

MOCK_METHOD1(onError, void(CURLcode errCode));
MOCK_METHOD0(onTimeout, void());
MOCK_METHOD2(onData, void(char *data, size_t datalen));
MOCK_METHOD4(onFinish, void(double content_length, long header_size, long httpcode, char *redirect_url));

The function like MOCK_* it function inside of google mock, just match the parameter type and numbers.

OK, mock define part is finished.

let's see this code:

Create the mock object:

shared_ptr<MockCallback>    mcallback(new StrictMock<MockCallback>);

 

policy->finishHandler = [&mcallback](double content_length, long header_size, long httpcode, char *redirect_url) {
EXPECT_EQ(httpcode, 200);
mcallback->onFinish(content_length, header_size, httpcode, redirect_url);
};

The finishHanlder is a std::function<> which can be a functor or lambda, in side this lambda, it will call the mock object. (you can define a simpler interface)

In the end,  we can assert the mock object:

    EXPECT_CALL((*mcallback.get()), onFinish(_,_, _, NULL)).Times(1);

This means, we expect this callback once, and with some parameter we, "_" is a special function, which means this is something we don't care, and all other values will be checked by gmock. If not match, some warning message will printed, and reported.

If the callback was not called, it will catch this error, if some uninteresting function is called, there will be a warning message.

Really useful tool!

There also some other benifits:

  1. gmock can check memory leak for your mock callback object, if it was leaked after test terminal, it will print error message like:

test_aio.cpp:198: ERROR: this mock object should be deleted but never is. Its address is @0x7fe1d0c0ce50.

 

If you want to know more about gmock, check google's gtest github: link