Fabric8:未设置'expect'时Mock Kubernetes Server无法创建资源
问题分析与解决方案
首先明确:@EnableKubernetesMockClient启用的KubernetesMockServer并非自动支持CRUD持久化的模拟服务,它本质是请求匹配式的mock工具——所有API请求都需要预先定义对应的预期响应,否则会返回404(Not Found)。你的错误就来自于没有为POST /apis/batch/v1/namespaces/test/jobs这个创建Job的请求设置预期响应。
两种可行解决思路
思路1:使用支持自动CRUD的本地嵌入式K8s服务器
如果你想要无需手动模拟每个请求、自动处理资源CRUD的测试环境,应该使用fabric8提供的LocalKubernetesServer,而非KubernetesMockServer。
配置示例如下:
import io.fabric8.kubernetes.api.model.batch.Job; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.server.local.LocalKubernetesServer; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class Test { private static LocalKubernetesServer server; private static KubernetesClient client; @BeforeAll static void setup() { server = new LocalKubernetesServer(); server.start(); client = server.getClient(); } @AfterAll static void teardown() { client.close(); server.stop(); } @Test public void test_create_custom_job() { MyJobDetails myJobDetails = new MyJobDetails(); String jobName = "job1-202211200345-prod"; myJobDetails.setName(jobName); // 其他属性设置... PlatformOperationsService svc = new PlatformOperationsService(client); svc.createCustomJob(myJobDetails); // 直接查询已创建的Job Job createdJob = client.batch().v1().jobs().list().getItems().get(0); assertEquals(jobName, createdJob.getMetadata().getName()); // 其他断言... } }
这个本地服务器会模拟真实K8s的CRUD行为,自动存储你创建的资源,无需手动设置请求预期。
思路2:为MockServer预先设置请求预期
如果必须使用KubernetesMockServer,需要为每个API请求(包括创建和查询)定义预期响应:
import io.fabric8.kubernetes.api.model.batch.Job; import io.fabric8.kubernetes.api.model.batch.JobBuilder; import io.fabric8.kubernetes.api.model.batch.JobListBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @EnableKubernetesMockClient public class Test { KubernetesMockServer server; KubernetesClient client; @Test public void test_create_custom_job() { MyJobDetails myJobDetails = new MyJobDetails(); String jobName = "job1-202211200345-prod"; myJobDetails.setName(jobName); // 其他属性设置... // 1. 预先设置创建Job的请求预期 Job mockJob = new JobBuilder() .withNewMetadata() .withName(jobName) .withNamespace("test") .endMetadata() // 匹配你的实际Job spec .withNewSpec() .endSpec() .build(); server.expect().post().withPath("/apis/batch/v1/namespaces/test/jobs") .andReturn(201, mockJob) .once(); // 2. 预先设置查询Job列表的请求预期 server.expect().get().withPath("/apis/batch/v1/namespaces/test/jobs") .andReturn(200, new JobListBuilder().addItems(mockJob).build()) .once(); PlatformOperationsService svc = new PlatformOperationsService(client); svc.createCustomJob(myJobDetails); Job createdJob = client.batch().v1().jobs().list().getItems().get(0); assertEquals(jobName, createdJob.getMetadata().getName()); // 其他断言... } }
这种方式需要你为每个API交互都定义预期,适合需要精确控制请求响应的场景,但不符合你“无需模拟PUT/POST操作”的需求。
内容的提问来源于stack exchange,提问作者Anish Nagaraj
相关产品推荐
相关产品推荐

