How to run spring boot integration test in Kubernetes

Viewed 750

I have a simple integration test for my spring boot application under the location src/intrgTest/groovy and below is the test

@AutoConfigureMockMvc
@WebMvcTest
class WebControllerTest extends Specification {

  @Autowired
  private MockMvc mvc

  def "when get is performed then the response has status 200 and content is 'Hello world!'"() {
    expect: "Status is 200 and the response is 'Hello world!'"
    mvc.perform(get("/hello"))
      .andExpect(status().isOk())
      .andReturn()
      .response
      .contentAsString == "Hello world!"
  }
}

When I create a pod in Kubernetes I want to run this test case to check the app is working fine. How can I achieve this?

Below is the deployment.yml file for kubernetes

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: spring-boot-deployment
spec:
  selector:
    matchLabels:
      app: spring-boot-app
  replicas: 2 
  template:
    metadata:
      labels:
        app: spring-boot-app
    spec:
      containers:
      - name: spring-boot-app
        image: spring-boot-test-images:63
        ports:
        - containerPort: 80
1 Answers

Looking at the test it's a health check rather than an integration test. Ideally integration tests should be run using mvn test as part of Continuous Integration before you perform the actual deployment and not after that.

You really don't need to write a test for health check and execute it after the application is deployed on kubernetes. You could simply define readiness probe in the deployment yaml and Kubernetes will perform a health check before marking the pod as READY and start to send traffic to it.

If you are using spring boot version older than 2.3 then you can make use of actuator endpoint /actuator/health and if you are using spring boot 2.3 then /actuator/health/readiness endpoint as readiness probe.

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: spring-boot-deployment
spec:
  selector:
    matchLabels:
      app: spring-boot-app
  replicas: 2 
  template:
    metadata:
      labels:
        app: spring-boot-app
    spec:
      containers:
      - name: spring-boot-app
        image: spring-boot-test-images:63
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            port: 8080
            path: /actuator/health
        initialDelaySeconds: 10

If you want to include tests on some external systems such as redis or dynamo as health check you could write a custom health indicator for that. Below example from spring provided RedisHealthIndicator

public class RedisHealthIndicator extends AbstractHealthIndicator {

    private final RedisConnectionFactory redisConnectionFactory;

    public RedisHealthIndicator(RedisConnectionFactory connectionFactory) {
        super("Redis health check failed");
        Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
        this.redisConnectionFactory = connectionFactory;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        RedisConnection connection = RedisConnectionUtils.getConnection(this.redisConnectionFactory);
        try {
            doHealthCheck(builder, connection);
        }
        finally {
            RedisConnectionUtils.releaseConnection(connection, this.redisConnectionFactory, false);
        }
    }

    private void doHealthCheck(Health.Builder builder, RedisConnection connection) {
        if (connection instanceof RedisClusterConnection) {
            RedisHealth.up(builder, ((RedisClusterConnection) connection).clusterGetClusterInfo());
        }
        else {
            RedisHealth.up(builder, connection.info());
        }
    }

}
Related