Search code examples
c++unit-testinggrpcgoogletestgooglemock

How to unit test gRPC asynchronous C++ client functions with google test


I'm trying to write unit tests for my C++ gRPC client, using google test. I'm using both synchronous and asynchronous rpc's, and I can't figure out how to use mock'ed version of asynchronous ones.

In my .proto file I have:

rpc foo(EmptyMessage) returns (FooReply) {}

From this protoc has generated mock stub with both synchronous and asynchronous calls:

  MOCK_METHOD3(foo, ::grpc::Status(::grpc::ClientContext* context, const ::EmptyMessage& request, ::FooReply* response));
  MOCK_METHOD3(AsyncfooRaw, ::grpc::ClientAsyncResponseReaderInterface< ::FooReply>*(::grpc::ClientContext* context, const ::EmptyMessage& request, ::grpc::CompletionQueue* cq));

I can succesfully mock synchronous calls with:

EXPECT_CALL(mockStub, foo).Times (1).WillOnce ([] (grpc::ClientContext *, const ::EmptyMessage &, ::FooReply *repl) {
        // I can set desired values to 'repl' here
        return grpc::Status::OK;
    });

Question: how can I use the mock'ed asynchronous foo() rpc?

I have tried for example:

EXPECT_CALL(mockStub, AsyncfooRaw).Times (1).WillOnce ([] (::grpc::ClientContext* context, const ::EmptyMessage& request, ::grpc::CompletionQueue* cq)
                                                                           -> grpc_impl::ClientAsyncResponseReaderInterface<::FooReply>* {
   ...

which compiles, but I get:

GMOCK WARNING:
Uninteresting mock function call - returning default value.
    Function call: AsyncfooRaw

which to my understanding means gmock does not find the handler for AsyncfooRaw I'm trying to provide.


Solution

  • Unfortunately, gRPC doesn't offer a way to create mocks for the async API. There were some historical constraints that made this infeasible when the async API was first developed, and as a result, the API wasn't really designed to support this.

    We might want to look at supporting this for the new callback-based API, which is intended to replace the async API. Feel free to file a feature request for this. However, it will require some investigation, and I'm not sure how quickly we'll be able to get to it.

    In the interim, the best work-around is to create a server implementation and add your mocks there, rather than mocking the client API directly.