This is an automated email from the ASF dual-hosted git repository.
wy471x pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 3af7bfc6a2 test: add controller tests for discovery and proxy selector
(#7511)
3af7bfc6a2 is described below
commit 3af7bfc6a2b4cab741c9a950ff5160ee749584b9
Author: wy471x <[email protected]>
AuthorDate: Fri Oct 16 21:35:48 2026 +0800
test: add controller tests for discovery and proxy selector (#7511)
Co-authored-by: wy471x <[email protected]>
---
.../admin/controller/DiscoveryControllerTest.java | 171 ++++++++++++++++++
.../controller/ProxySelectorControllerTest.java | 201 +++++++++++++++++++++
2 files changed, 372 insertions(+)
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/DiscoveryControllerTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/DiscoveryControllerTest.java
new file mode 100644
index 0000000000..802fb75ca2
--- /dev/null
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/DiscoveryControllerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.controller;
+
+import org.apache.shenyu.admin.exception.ExceptionHandlers;
+import org.apache.shenyu.admin.mapper.NamespaceMapper;
+import org.apache.shenyu.admin.model.dto.DiscoveryDTO;
+import org.apache.shenyu.admin.model.vo.DiscoveryVO;
+import org.apache.shenyu.admin.service.DiscoveryService;
+import org.apache.shenyu.admin.spring.SpringBeanUtils;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * Test cases for DiscoveryController.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public final class DiscoveryControllerTest {
+
+ private static final String NAMESPACE_ID = "default";
+
+ private MockMvc mockMvc;
+
+ @InjectMocks
+ private DiscoveryController discoveryController;
+
+ @Mock
+ private DiscoveryService discoveryService;
+
+ @Mock
+ private NamespaceMapper namespaceMapper;
+
+ @BeforeEach
+ public void setUp() {
+ this.mockMvc = MockMvcBuilders.standaloneSetup(discoveryController)
+ .setControllerAdvice(new ExceptionHandlers(null))
+ .build();
+
SpringBeanUtils.getInstance().setApplicationContext(mock(ConfigurableApplicationContext.class));
+
when(SpringBeanUtils.getInstance().getBean(NamespaceMapper.class)).thenReturn(namespaceMapper);
+ }
+
+ @Test
+ public void testTypeEnumsShouldReturnServiceResult() throws Exception {
+ when(discoveryService.typeEnums()).thenReturn(List.of("zookeeper",
"etcd"));
+
+
this.mockMvc.perform(MockMvcRequestBuilders.get("/discovery/typeEnums"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.data[0]").value("zookeeper"))
+ .andExpect(jsonPath("$.data[1]").value("etcd"));
+ }
+
+ @Test
+ public void testDiscoveryShouldDelegateToService() throws Exception {
+ DiscoveryVO discoveryVO = new DiscoveryVO();
+ discoveryVO.setPluginName("divide");
+ when(discoveryService.discovery("divide", "proxy",
NAMESPACE_ID)).thenReturn(discoveryVO);
+
+ this.mockMvc.perform(MockMvcRequestBuilders.get("/discovery")
+ .param("pluginName", "divide")
+ .param("level", "proxy")
+ .param("namespaceId", NAMESPACE_ID))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.data.pluginName").value("divide"));
+ }
+
+ @Test
+ public void testCreateOrUpdateShouldDelegateToService() throws Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+ DiscoveryDTO discoveryDTO = buildDiscoveryDTO();
+ DiscoveryVO discoveryVO = new DiscoveryVO();
+ discoveryVO.setDiscoveryName(discoveryDTO.getName());
+
when(discoveryService.createOrUpdate(any(DiscoveryDTO.class))).thenReturn(discoveryVO);
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/discovery/insertOrUpdate")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(GsonUtils.getInstance().toJson(discoveryDTO)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+
.andExpect(jsonPath("$.data.discoveryName").value("test-discovery"));
+ verify(discoveryService).createOrUpdate(any(DiscoveryDTO.class));
+ }
+
+ @Test
+ public void testCreateOrUpdateWithMissingNameShouldFail() throws Exception
{
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/discovery/insertOrUpdate")
+ .contentType(MediaType.APPLICATION_JSON)
+
.content("{\"level\":\"proxy\",\"pluginName\":\"divide\",\"type\":\"zookeeper\","
+ +
"\"serverList\":\"localhost:2181\",\"props\":\"{}\",\"namespaceId\":\"default\"}"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.message", containsString("name not
null")));
+ }
+
+ @Test
+ public void testCreateOrUpdateWithNonExistentNamespaceShouldFail() throws
Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(false);
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/discovery/insertOrUpdate")
+ .contentType(MediaType.APPLICATION_JSON)
+
.content(GsonUtils.getInstance().toJson(buildDiscoveryDTO())))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.message", containsString("namespaceId
is not existed")));
+ }
+
+ @Test
+ public void testDeleteWithExistentNamespaceShouldSucceed() throws
Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+ when(discoveryService.delete("discovery-1",
NAMESPACE_ID)).thenReturn("success");
+
+
this.mockMvc.perform(MockMvcRequestBuilders.delete("/discovery/{discoveryId}",
"discovery-1")
+ .param("namespaceId", NAMESPACE_ID))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.data").value("success"));
+ verify(discoveryService).delete("discovery-1", NAMESPACE_ID);
+ }
+
+ private DiscoveryDTO buildDiscoveryDTO() {
+ DiscoveryDTO discoveryDTO = new DiscoveryDTO();
+ discoveryDTO.setId("discovery-1");
+ discoveryDTO.setLevel("proxy");
+ discoveryDTO.setName("test-discovery");
+ discoveryDTO.setPluginName("divide");
+ discoveryDTO.setType("zookeeper");
+ discoveryDTO.setServerList("localhost:2181");
+ discoveryDTO.setProps("{}");
+ discoveryDTO.setNamespaceId(NAMESPACE_ID);
+ return discoveryDTO;
+ }
+}
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ProxySelectorControllerTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ProxySelectorControllerTest.java
new file mode 100644
index 0000000000..4b8c632938
--- /dev/null
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ProxySelectorControllerTest.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.controller;
+
+import org.apache.shenyu.admin.exception.ExceptionHandlers;
+import org.apache.shenyu.admin.mapper.NamespaceMapper;
+import org.apache.shenyu.admin.mapper.ProxySelectorMapper;
+import org.apache.shenyu.admin.model.dto.ProxySelectorAddDTO;
+import org.apache.shenyu.admin.model.page.CommonPager;
+import org.apache.shenyu.admin.model.page.PageParameter;
+import org.apache.shenyu.admin.model.vo.ProxySelectorVO;
+import org.apache.shenyu.admin.service.ProxySelectorService;
+import org.apache.shenyu.admin.spring.SpringBeanUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * Test cases for ProxySelectorController.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public final class ProxySelectorControllerTest {
+
+ private static final String NAMESPACE_ID = "default";
+
+ private MockMvc mockMvc;
+
+ @InjectMocks
+ private ProxySelectorController proxySelectorController;
+
+ @Mock
+ private ProxySelectorService proxySelectorService;
+
+ @Mock
+ private NamespaceMapper namespaceMapper;
+
+ @Mock
+ private ProxySelectorMapper proxySelectorMapper;
+
+ @BeforeEach
+ public void setUp() {
+ this.mockMvc = MockMvcBuilders.standaloneSetup(proxySelectorController)
+ .setControllerAdvice(new ExceptionHandlers(null))
+ .build();
+
SpringBeanUtils.getInstance().setApplicationContext(mock(ConfigurableApplicationContext.class));
+
when(SpringBeanUtils.getInstance().getBean(NamespaceMapper.class)).thenReturn(namespaceMapper);
+
when(SpringBeanUtils.getInstance().getBean(ProxySelectorMapper.class)).thenReturn(proxySelectorMapper);
+ }
+
+ @Test
+ public void testQueryProxySelectorShouldReturnPage() throws Exception {
+ ProxySelectorVO proxySelectorVO = new ProxySelectorVO();
+ proxySelectorVO.setName("test-proxy-selector");
+ CommonPager<ProxySelectorVO> commonPager = new CommonPager<>(new
PageParameter(1, 12),
+ Collections.singletonList(proxySelectorVO));
+ when(proxySelectorService.listByPage(any())).thenReturn(commonPager);
+
+ this.mockMvc.perform(MockMvcRequestBuilders.get("/proxy-selector")
+ .param("name", "test-proxy-selector")
+ .param("currentPage", "1")
+ .param("pageSize", "12")
+ .param("namespaceId", NAMESPACE_ID))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+
.andExpect(jsonPath("$.data.dataList[0].name").value("test-proxy-selector"));
+ }
+
+ @Test
+ public void testAddProxySelectorShouldDelegateToService() throws Exception
{
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+
when(proxySelectorService.create(any(ProxySelectorAddDTO.class))).thenReturn("success");
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/proxy-selector/addProxySelector")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(buildProxySelectorJson()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.message").value("success"));
+ verify(proxySelectorService).create(any(ProxySelectorAddDTO.class));
+ }
+
+ @Test
+ public void testAddProxySelectorWithMissingNameShouldFail() throws
Exception {
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/proxy-selector/addProxySelector")
+ .contentType(MediaType.APPLICATION_JSON)
+
.content("{\"pluginName\":\"divide\",\"type\":\"zookeeper\",\"namespaceId\":\"default\","
+ +
"\"discovery\":{\"discoveryType\":\"zookeeper\",\"serverList\":\"localhost:2181\"}}"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.message", containsString("name: must
not be blank")));
+ }
+
+ @Test
+ public void testAddProxySelectorWithNonExistentNamespaceShouldFail()
throws Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(false);
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/proxy-selector/addProxySelector")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(buildProxySelectorJson()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.message", containsString("namespaceId
is not existed")));
+ }
+
+ @Test
+ public void testUpdateProxySelectorShouldSetIdFromPath() throws Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+ when(proxySelectorMapper.existed("proxy-selector-1")).thenReturn(true);
+
when(proxySelectorService.createOrUpdate(any(ProxySelectorAddDTO.class))).thenReturn("success");
+
+
this.mockMvc.perform(MockMvcRequestBuilders.put("/proxy-selector/{id}",
"proxy-selector-1")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(buildProxySelectorJson()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.message").value("success"));
+
+ ArgumentCaptor<ProxySelectorAddDTO> captor =
ArgumentCaptor.forClass(ProxySelectorAddDTO.class);
+ verify(proxySelectorService).createOrUpdate(captor.capture());
+ assertEquals("proxy-selector-1", captor.getValue().getId());
+ }
+
+ @Test
+ public void testDeleteProxySelectorsShouldDelegateToService() throws
Exception {
+ List<String> ids = List.of("id-1", "id-2");
+ when(proxySelectorService.delete(ids)).thenReturn("success");
+
+
this.mockMvc.perform(MockMvcRequestBuilders.delete("/proxy-selector/batch")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("[\"id-1\",\"id-2\"]"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.message").value("success"));
+ verify(proxySelectorService).delete(ids);
+ }
+
+ @Test
+ public void testFetchDataShouldDelegateToService() throws Exception {
+
this.mockMvc.perform(MockMvcRequestBuilders.put("/proxy-selector/fetch/{discoveryHandlerId}",
"handler-1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200));
+ verify(proxySelectorService).fetchData("handler-1");
+ }
+
+ @Test
+ public void testBindingSelectorShouldDelegateToService() throws Exception {
+ when(namespaceMapper.existed(NAMESPACE_ID)).thenReturn(true);
+
when(proxySelectorService.bindingDiscoveryHandler(any(ProxySelectorAddDTO.class))).thenReturn("success");
+
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/proxy-selector/binding")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(buildProxySelectorJson()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(200))
+ .andExpect(jsonPath("$.message").value("success"));
+
verify(proxySelectorService).bindingDiscoveryHandler(any(ProxySelectorAddDTO.class));
+ }
+
+ private String buildProxySelectorJson() {
+ return
"{\"name\":\"test-proxy-selector\",\"pluginName\":\"divide\",\"type\":\"zookeeper\","
+ +
"\"forwardPort\":8080,\"props\":\"{}\",\"namespaceId\":\"default\","
+ +
"\"discovery\":{\"discoveryType\":\"zookeeper\",\"serverList\":\"localhost:2181\",\"props\":\"{}\"}}";
+ }
+}