This project demonstrates a Spring Boot application that communicates with a gRPC server, along with comprehensive integration testing using Cucumber, Testcontainers, and a mock gRPC server.
src/main/proto/helloworld.proto: Proto definition file for the gRPC servicesrc/main/java/com/example/grpcclient: Main application codeGrpcClientApplication.java: Spring Boot application entry pointconfig/GrpcClientConfig.java: Configuration for gRPC client with dynamic property supportservice/GreeterService.java: Service to handle gRPC client operationscontroller/GreeterController.java: REST controller exposing HTTP endpointscontroller/OverrideController.java: Controller for handling mock response overridesmodel/: Data models for REST API requests and responses
src/test/java/com/example/grpcclient: Test codeCucumberIntegrationTest.java: Cucumber test runnerCucumberTestConfig.java: Spring configuration for Cucumber testscontainers/GrpcMockServerContainer.java: Testcontainers setup for the mock gRPC serversteps/GreeterServiceSteps.java: Cucumber step definitions
src/test/resources/features: Cucumber feature filesgreeter_service.feature: BDD scenarios for testing the gRPC client
src/test/resources/responses: Mock response configurationsresponses.json: Predefined responses for the mock gRPC server
src/test/resources/protos: Proto files for the mock server
The application exposes the following REST endpoints:
-
Say Hello
- URL:
POST /api/greeter/hello - Request Body:
{ "name": "YourName" } - Response: The greeting message from the gRPC server
- URL:
-
Say Goodbye
- URL:
POST /api/greeter/goodbye - Request Body:
{ "name": "YourName", "formal": true } - Response: The goodbye message from the gRPC server
- URL:
The application supports dynamic configuration of the gRPC server connection:
- In production: Uses the configured values from
application.properties - In tests: Uses dynamic properties from the Testcontainers mock server
The integration tests use a Docker-based mock gRPC server with the following features:
- Predefined responses based on request content
- Dynamic response overrides via HTTP API
- File system bindings for proto definitions and response configurations
# Server configuration
server.port=8081
# gRPC server configuration (default values)
grpc.server.host=localhost
grpc.server.port=9090
# Logging
logging.level.com.example.grpcclient=INFO# Test configuration
spring.main.allow-bean-definition-overriding=true
spring.main.lazy-initialization=true
# Logging for tests
logging.level.com.example.grpcclient=DEBUG
# Default gRPC server settings (will be overridden by dynamic properties)
grpc.server.host=localhost
grpc.server.port=9090mvn spring-boot:runmvn testYou can test the API using curl or any REST client:
# Say Hello
curl -X POST http://localhost:8081/api/greeter/hello -H "Content-Type: application/json" -d "{\"name\":\"John\"}"
# Say Goodbye
curl -X POST http://localhost:8081/api/greeter/goodbye -H "Content-Type: application/json" -d "{\"name\":\"John\",\"formal\":true}"
# Set Override Response
curl -X POST http://localhost:8081/api/override -H "Content-Type: application/json" -d "{\"serviceName\":\"helloworld.Greeter\",\"methodName\":\"sayHello\",\"responsePayload\":{\"message\":\"Custom response\"}}"Note: When using Windows PowerShell, ensure JSON payloads are properly escaped as shown above.
-
Dynamic Property Handling: The application uses a combination of system properties and Spring's
@DynamicPropertySourceto ensure the gRPC client uses the correct server details during tests. -
Lazy Initialization: The gRPC client beans are lazily initialized to ensure they pick up the latest configuration values.
-
Testcontainers Integration: The mock gRPC server runs in a Docker container managed by Testcontainers, with proper lifecycle management.
-
Override Mechanism: The application includes a mechanism to override gRPC responses for testing purposes, allowing for flexible test scenarios.