如何在Kubernetes中运行Spring Boot集成测试

问题描述

我在src/intrgTest/groovy位置为我的spring boot应用程序做了一个简单的集成测试,下面是测试

@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!"
  }
}

当我在Kubernetes中创建Pod时,我想运行此测试用例以检查应用程序是否正常运行。我该如何实现?

下面是kubernetes的deployment.yml文件

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

解决方法

看一下测试,它是运行状况检查,而不是集成测试。理想情况下,应该在进行实际部署之前而不是之后,将mvn test作为持续集成的一部分运行集成测试。

在将应用程序部署到kubernetes上之后,您真的不需要编写运行状况检查测试并执行它。您只需在部署yaml中定义readiness probe,Kubernetes将执行健康检查,然后将Pod标记为READY并开始向其发送流量。

如果使用的弹簧引导版本早于2.3,则可以使用执行器端点/actuator/health;如果使用的是弹簧引导2.3,则可以将/actuator/health/readiness端点用作就绪探针。

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

如果您想在某些外部系统(例如redis或dynamo)上包含测试作为运行状况检查,则可以为此编写一个custom health indicator。下面的示例来自spring提供的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());
        }
    }

}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...