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\":\"{}\"}}";
+    }
+}

Reply via email to