gRPC is a high-performance RPC framework from Google used for service-to-service communication. Instead of JSON over REST endpoints, clients call methods defined in a .proto file and exchange compact binary Protocol Buffers messages over HTTP/2. You can't test it with a plain REST client, so this guide covers the tools and the test approach.
gRPC vs REST for Testers
| REST | gRPC | |
|---|---|---|
| Contract | Optional OpenAPI spec | Mandatory .proto file |
| Payload | JSON (text) | Protocol Buffers (binary) |
| Transport | HTTP/1.1 or 2 | HTTP/2 |
| Call types | Request–response | Unary, server streaming, client streaming, bidirectional streaming |
| Errors | HTTP status codes | gRPC status codes (OK, INVALID_ARGUMENT, NOT_FOUND, UNAUTHENTICATED, DEADLINE_EXCEEDED…) |
| Manual tools | Postman, curl | grpcurl, Postman (gRPC request), BloomRPC-style GUIs |
Testing gRPC Manually with grpcurl
# List services (needs server reflection enabled, or pass -proto)
grpcurl -plaintext localhost:50051 list
# Describe a method
grpcurl -plaintext localhost:50051 describe user.UserService.GetUser
# Call it with a JSON-formatted request
grpcurl -plaintext -d '{"id": "42"}' localhost:50051 user.UserService/GetUser
Automated gRPC Tests in Java
// gRPC test with grpc-java library
// Proto definition (user.proto):
// service UserService {
// rpc GetUser(GetUserRequest) returns (UserResponse);
// rpc ListUsers(ListUsersRequest) returns (stream UserResponse);
// }
public class GrpcUserServiceTest {
private ManagedChannel channel;
private UserServiceGrpc.UserServiceBlockingStub stub;
@BeforeClass
public void setup() {
channel = ManagedChannelBuilder
.forAddress(ConfigReader.get("grpc.host"),
Integer.parseInt(ConfigReader.get("grpc.port")))
.usePlaintext() // no TLS for test env
.build();
// Add auth interceptor
stub = UserServiceGrpc.newBlockingStub(channel)
.withInterceptors(new AuthHeaderInterceptor(TokenManager.getServiceToken()));
}
@Test
public void getUser_validId_returnsUser() {
GetUserRequest request = GetUserRequest.newBuilder()
.setId(42L)
.build();
UserResponse response = stub.getUser(request);
assertThat(response.getId()) .isEqualTo(42L);
assertThat(response.getName()) .isNotEmpty();
assertThat(response.getIsActive()).isTrue();
}
@Test
public void getUser_notFound_throwsStatusRuntimeException() {
GetUserRequest request = GetUserRequest.newBuilder().setId(9999L).build();
assertThatThrownBy(() -> stub.getUser(request))
.isInstanceOf(StatusRuntimeException.class)
.satisfies(e -> {
StatusRuntimeException sre = (StatusRuntimeException) e;
assertThat(sre.getStatus().getCode()).isEqualTo(Status.Code.NOT_FOUND);
assertThat(sre.getStatus().getDescription()).contains("user not found");
});
}
@AfterClass
public void teardown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
}
| gRPC Status Code | Meaning | REST Equivalent |
|---|---|---|
| OK (0) | Success | 200 OK |
| CANCELLED (1) | Operation cancelled by client | — |
| NOT_FOUND (5) | Resource not found | 404 Not Found |
| ALREADY_EXISTS (6) | Duplicate resource | 409 Conflict |
| PERMISSION_DENIED (7) | Not authorised | 403 Forbidden |
| UNAUTHENTICATED (16) | Missing/invalid credentials | 401 Unauthorized |
| RESOURCE_EXHAUSTED (8) | Rate limit exceeded | 429 Too Many Requests |
| INVALID_ARGUMENT (3) | Invalid request data | 400 / 422 |
| INTERNAL (13) | Server error | 500 Internal Server Error |
| UNAVAILABLE (14) | Service temporarily unavailable | 503 Service Unavailable |
gRPC Test Checklist
- Every RPC: valid request, missing and invalid fields (expect
INVALID_ARGUMENT), unknown IDs (NOT_FOUND), no or bad credentials (UNAUTHENTICATED/PERMISSION_DENIED). - Deadlines: set a short deadline and check the client gets
DEADLINE_EXCEEDEDrather than hanging. - Streaming: number and order of streamed messages, behaviour when the client cancels mid-stream.
- Backward compatibility: old clients still work after the proto changes (adding fields is safe; renumbering or changing field types is not).
- Metadata: headers such as auth tokens and correlation IDs are passed and enforced.
FAQs
Can Postman test gRPC APIs?
Yes. Postman supports gRPC requests: import the .proto file or use server reflection, choose the method, and send a message written as JSON.
What is the gRPC equivalent of a 404?
The NOT_FOUND status code. gRPC has its own set of status codes, returned in the response trailers, instead of HTTP status codes.
Can REST Assured test gRPC?
No. REST Assured speaks HTTP/JSON. Use the generated gRPC client stubs in Java tests (with JUnit or TestNG), or tools such as grpcurl, Postman or Karate's gRPC support.