问题描述
我在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());
}
}
}