This is an automated email from the ASF dual-hosted git repository.

Aias00 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 dfcf8b54f9 fix: scope discovery update and delete by namespace (#6827) 
(#7007)
dfcf8b54f9 is described below

commit dfcf8b54f97b4910d72695b9d72a62228fb85512
Author: wy471x <[email protected]>
AuthorDate: Thu Sep 3 08:54:46 2026 +0800

    fix: scope discovery update and delete by namespace (#6827) (#7007)
    
    Add namespace_id predicates to the discovery update, updateSelective
    and delete statements so that discovery configs can only be modified
    within the caller's namespace. DiscoveryService#delete now validates
    the namespace of the target discovery before processing, and the
    DELETE /discovery/{discoveryId} endpoint requires a namespaceId
    parameter and plugin edit/delete permissions.
    
    Co-authored-by: aias00 <[email protected]>
---
 .../admin/controller/DiscoveryController.java      |  13 +-
 .../shenyu/admin/mapper/DiscoveryMapper.java       |   5 +-
 .../shenyu/admin/service/DiscoveryService.java     |   3 +-
 .../admin/service/impl/DiscoveryServiceImpl.java   |   8 +-
 .../service/impl/ProxySelectorServiceImpl.java     |   2 +-
 .../admin/service/impl/SelectorServiceImpl.java    |   2 +-
 .../main/resources/mappers/discovery-sqlmap.xml    |   8 +-
 .../shenyu/admin/mapper/DiscoveryMapperTest.java   | 136 +++++++++++++++++++++
 .../admin/service/DiscoveryServiceImplTest.java    | 130 ++++++++++++++++++++
 9 files changed, 294 insertions(+), 13 deletions(-)

diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/DiscoveryController.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/DiscoveryController.java
index 921a60d86d..09e78367e0 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/DiscoveryController.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/DiscoveryController.java
@@ -18,15 +18,19 @@
 package org.apache.shenyu.admin.controller;
 
 import org.apache.shenyu.admin.aspect.annotation.RestApi;
+import org.apache.shenyu.admin.mapper.NamespaceMapper;
 import org.apache.shenyu.admin.model.dto.DiscoveryDTO;
 import org.apache.shenyu.admin.model.result.ShenyuAdminResult;
 import org.apache.shenyu.admin.service.DiscoveryService;
 import org.apache.shenyu.admin.utils.ShenyuResultMessage;
+import org.apache.shenyu.admin.validation.annotation.Existed;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import jakarta.validation.Valid;
 
@@ -72,6 +76,7 @@ public class DiscoveryController {
      * @return {@linkplain ShenyuAdminResult}
      */
     @PostMapping("/insertOrUpdate")
+    @RequiresPermissions("system:plugin:edit")
     public ShenyuAdminResult createOrUpdate(@Valid @RequestBody final 
DiscoveryDTO discoveryDTO) {
         return ShenyuAdminResult.success(ShenyuResultMessage.SUCCESS, 
discoveryService.createOrUpdate(discoveryDTO));
     }
@@ -80,11 +85,15 @@ public class DiscoveryController {
      * delete by id.
      *
      * @param discoveryId discoveryId
+     * @param namespaceId namespaceId
      * @return {@linkplain ShenyuAdminResult}
      */
     @DeleteMapping("/{discoveryId}")
-    public ShenyuAdminResult delete(@PathVariable("discoveryId") final String 
discoveryId) {
-        return ShenyuAdminResult.success(ShenyuResultMessage.SUCCESS, 
discoveryService.delete(discoveryId));
+    @RequiresPermissions("system:plugin:delete")
+    public ShenyuAdminResult delete(@PathVariable("discoveryId") final String 
discoveryId,
+                                    @Existed(message = "namespaceId is not 
existed", provider = NamespaceMapper.class)
+                                    @RequestParam("namespaceId") final String 
namespaceId) {
+        return ShenyuAdminResult.success(ShenyuResultMessage.SUCCESS, 
discoveryService.delete(discoveryId, namespaceId));
     }
 
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryMapper.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryMapper.java
index 48c26d5577..ced0c8ec95 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryMapper.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryMapper.java
@@ -126,12 +126,13 @@ public interface DiscoveryMapper extends ExistProvider {
     int updateSelective(DiscoveryDO discoveryDO);
 
     /**
-     * delete discovery by id.
+     * delete discovery by id and namespace id.
      *
      * @param id primary key.
+     * @param namespaceId namespace id.
      * @return rows.
      */
-    int delete(String id);
+    int delete(@Param("id") String id, @Param("namespaceId") String 
namespaceId);
 
     /**
      * selectBySelectorNameAndPluginName.
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
index b57571e1ed..c313edbd0a 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
@@ -69,9 +69,10 @@ public interface DiscoveryService {
      * delete by id.
      *
      * @param discoveryId discoveryId
+     * @param namespaceId namespaceId
      * @return msg
      */
-    String delete(String discoveryId);
+    String delete(String discoveryId, String namespaceId);
 
     /**
      * syncData.
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
index af1d4b2c11..a905be9c43 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
@@ -189,16 +189,20 @@ public class DiscoveryServiceImpl implements 
DiscoveryService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public String delete(final String discoveryId) {
+    public String delete(final String discoveryId, final String namespaceId) {
         List<DiscoveryHandlerDO> discoveryHandlerDOS = 
discoveryHandlerMapper.selectByDiscoveryId(discoveryId);
         if (CollectionUtils.isNotEmpty(discoveryHandlerDOS)) {
             LOG.warn("shenyu this discovery has discoveryHandler can't be 
delete");
             throw new ShenyuException("shenyu this discovery has 
discoveryHandler can't be delete");
         }
         DiscoveryDO discoveryDO = discoveryMapper.selectById(discoveryId);
+        if (Objects.isNull(discoveryDO) || 
!Objects.equals(discoveryDO.getNamespaceId(), namespaceId)) {
+            LOG.warn("shenyu discovery {} is not found in namespace {}", 
discoveryId, namespaceId);
+            throw new ShenyuException("shenyu this discovery is not found in 
current namespace");
+        }
         DiscoveryProcessor discoveryProcessor = 
discoveryProcessorHolder.chooseProcessor(discoveryDO.getDiscoveryType());
         discoveryProcessor.removeDiscovery(discoveryDO);
-        discoveryMapper.delete(discoveryId);
+        discoveryMapper.delete(discoveryId, namespaceId);
         return ShenyuResultMessage.DELETE_SUCCESS;
     }
 
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java
index d439a4e427..5760608411 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java
@@ -181,7 +181,7 @@ public class ProxySelectorServiceImpl implements 
ProxySelectorService {
                 
discoveryProcessor.removeProxySelector(DiscoveryTransfer.INSTANCE.mapToDTO(discoveryHandlerDO),
 DiscoveryTransfer.INSTANCE.mapToDTO(proxySelectorDO));
                 if 
(DiscoveryLevel.SELECTOR.getCode().equals(discoveryDO.getDiscoveryLevel())) {
                     discoveryProcessor.removeDiscovery(discoveryDO);
-                    discoveryMapper.delete(discoveryDO.getId());
+                    discoveryMapper.delete(discoveryDO.getId(), 
discoveryDO.getNamespaceId());
                 }
                 
discoveryUpstreamMapper.deleteByDiscoveryHandlerId(discoveryHandlerDO.getId());
                 discoveryHandlerMapper.delete(discoveryHandlerDO.getId());
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java
index f44132f4de..c1434b3864 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java
@@ -329,7 +329,7 @@ public class SelectorServiceImpl implements SelectorService 
{
                 if 
(DiscoveryLevel.SELECTOR.getCode().equals(discoveryDO.getDiscoveryLevel())) {
                     discoveryProcessor.removeDiscovery(discoveryDO);
                     
discoveryProcessor.removeSelectorUpstream(proxySelectorDTO);
-                    discoveryMapper.delete(discoveryDO.getId());
+                    discoveryMapper.delete(discoveryDO.getId(), 
discoveryDO.getNamespaceId());
                 }
             }
         }
diff --git a/shenyu-admin/src/main/resources/mappers/discovery-sqlmap.xml 
b/shenyu-admin/src/main/resources/mappers/discovery-sqlmap.xml
index fb84755e0c..c4aa668d72 100644
--- a/shenyu-admin/src/main/resources/mappers/discovery-sqlmap.xml
+++ b/shenyu-admin/src/main/resources/mappers/discovery-sqlmap.xml
@@ -214,7 +214,7 @@
         server_list = #{serverList, jdbcType=VARCHAR},
         plugin_name = #{pluginName, jdbcType=VARCHAR},
         props = #{props, jdbcType=LONGVARCHAR}
-        WHERE id = #{id, jdbcType=VARCHAR}
+        WHERE id = #{id, jdbcType=VARCHAR} AND namespace_id = #{namespaceId, 
jdbcType=VARCHAR}
     </update>
 
     <update id="updateSelective" 
parameterType="org.apache.shenyu.admin.model.entity.DiscoveryDO">
@@ -245,12 +245,12 @@
                 props = #{props, jdbcType=LONGVARCHAR},
             </if>
         </set>
-        WHERE id = #{id, jdbcType=VARCHAR}
+        WHERE id = #{id, jdbcType=VARCHAR} AND namespace_id = #{namespaceId, 
jdbcType=VARCHAR}
     </update>
 
-    <delete id="delete" parameterType="java.lang.String">
+    <delete id="delete">
         DELETE
         FROM discovery
-        WHERE id = #{id, jdbcType=VARCHAR}
+        WHERE id = #{id, jdbcType=VARCHAR} AND namespace_id = #{namespaceId, 
jdbcType=VARCHAR}
     </delete>
 </mapper>
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryMapperTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryMapperTest.java
new file mode 100644
index 0000000000..1501866fa3
--- /dev/null
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryMapperTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.mapper;
+
+import org.apache.shenyu.admin.AbstractSpringIntegrationTest;
+import org.apache.shenyu.admin.model.entity.DiscoveryDO;
+import org.apache.shenyu.common.utils.UUIDUtils;
+import org.junit.jupiter.api.Test;
+
+import jakarta.annotation.Resource;
+import java.sql.Timestamp;
+
+import static 
org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+
+/**
+ * Test cases for DiscoveryMapper.
+ */
+public class DiscoveryMapperTest extends AbstractSpringIntegrationTest {
+
+    private static final String ANOTHER_NAMESPACE_ID = "another-namespace-id";
+
+    @Resource
+    private DiscoveryMapper discoveryMapper;
+
+    @Test
+    public void deleteScopedByNamespace() {
+        DiscoveryDO discoveryInNamespace = buildDiscoveryDO();
+        DiscoveryDO discoveryInAnotherNamespace = buildDiscoveryDO();
+        discoveryInAnotherNamespace.setNamespaceId(ANOTHER_NAMESPACE_ID);
+        assertThat(discoveryMapper.insert(discoveryInNamespace), equalTo(1));
+        assertThat(discoveryMapper.insert(discoveryInAnotherNamespace), 
equalTo(1));
+
+        // wrong namespace: delete nothing
+        assertThat(discoveryMapper.delete(discoveryInNamespace.getId(), 
ANOTHER_NAMESPACE_ID), equalTo(0));
+        
assertThat(discoveryMapper.selectById(discoveryInNamespace.getId()).getId(), 
equalTo(discoveryInNamespace.getId()));
+        
assertThat(discoveryMapper.selectById(discoveryInAnotherNamespace.getId()).getId(),
 equalTo(discoveryInAnotherNamespace.getId()));
+
+        // matching namespace: delete only that row
+        assertThat(discoveryMapper.delete(discoveryInNamespace.getId(), 
SYS_DEFAULT_NAMESPACE_ID), equalTo(1));
+        assertThat(discoveryMapper.selectById(discoveryInNamespace.getId()), 
nullValue());
+        
assertThat(discoveryMapper.selectById(discoveryInAnotherNamespace.getId()).getId(),
 equalTo(discoveryInAnotherNamespace.getId()));
+
+        // cleanup
+        assertThat(discoveryMapper.delete(discoveryInAnotherNamespace.getId(), 
ANOTHER_NAMESPACE_ID), equalTo(1));
+    }
+
+    @Test
+    public void updateScopedByNamespace() {
+        DiscoveryDO discoveryInNamespace = buildDiscoveryDO();
+        DiscoveryDO discoveryInAnotherNamespace = buildDiscoveryDO();
+        discoveryInAnotherNamespace.setNamespaceId(ANOTHER_NAMESPACE_ID);
+        assertThat(discoveryMapper.insert(discoveryInNamespace), equalTo(1));
+        assertThat(discoveryMapper.insert(discoveryInAnotherNamespace), 
equalTo(1));
+
+        DiscoveryDO updated = buildDiscoveryDO();
+        updated.setId(discoveryInNamespace.getId());
+        updated.setServerList("http://localhost:9999";);
+        updated.setNamespaceId(ANOTHER_NAMESPACE_ID);
+
+        // wrong namespace: update nothing
+        assertThat(discoveryMapper.update(updated), equalTo(0));
+
+        // matching namespace: update only that row
+        updated.setNamespaceId(SYS_DEFAULT_NAMESPACE_ID);
+        assertThat(discoveryMapper.update(updated), equalTo(1));
+        
assertThat(discoveryMapper.selectById(discoveryInNamespace.getId()).getServerList(),
 equalTo("http://localhost:9999";));
+        
assertThat(discoveryMapper.selectById(discoveryInAnotherNamespace.getId()).getServerList(),
 equalTo(discoveryInAnotherNamespace.getServerList()));
+
+        // cleanup
+        assertThat(discoveryMapper.delete(discoveryInNamespace.getId(), 
SYS_DEFAULT_NAMESPACE_ID), equalTo(1));
+        assertThat(discoveryMapper.delete(discoveryInAnotherNamespace.getId(), 
ANOTHER_NAMESPACE_ID), equalTo(1));
+    }
+
+    @Test
+    public void updateSelectiveScopedByNamespace() {
+        DiscoveryDO discoveryInNamespace = buildDiscoveryDO();
+        DiscoveryDO discoveryInAnotherNamespace = buildDiscoveryDO();
+        discoveryInAnotherNamespace.setNamespaceId(ANOTHER_NAMESPACE_ID);
+        assertThat(discoveryMapper.insert(discoveryInNamespace), equalTo(1));
+        assertThat(discoveryMapper.insert(discoveryInAnotherNamespace), 
equalTo(1));
+
+        DiscoveryDO updated = DiscoveryDO.builder()
+                .id(discoveryInNamespace.getId())
+                .serverList("http://localhost:9998";)
+                .namespaceId(ANOTHER_NAMESPACE_ID)
+                .dateUpdated(new Timestamp(System.currentTimeMillis()))
+                .build();
+
+        // wrong namespace: update nothing
+        assertThat(discoveryMapper.updateSelective(updated), equalTo(0));
+
+        // matching namespace: update only that row
+        updated.setNamespaceId(SYS_DEFAULT_NAMESPACE_ID);
+        assertThat(discoveryMapper.updateSelective(updated), equalTo(1));
+        
assertThat(discoveryMapper.selectById(discoveryInNamespace.getId()).getServerList(),
 equalTo("http://localhost:9998";));
+        
assertThat(discoveryMapper.selectById(discoveryInAnotherNamespace.getId()).getServerList(),
 equalTo(discoveryInAnotherNamespace.getServerList()));
+
+        // cleanup
+        assertThat(discoveryMapper.delete(discoveryInNamespace.getId(), 
SYS_DEFAULT_NAMESPACE_ID), equalTo(1));
+        assertThat(discoveryMapper.delete(discoveryInAnotherNamespace.getId(), 
ANOTHER_NAMESPACE_ID), equalTo(1));
+    }
+
+    private DiscoveryDO buildDiscoveryDO() {
+        Timestamp now = new Timestamp(System.currentTimeMillis());
+        return DiscoveryDO.builder()
+                .id(UUIDUtils.getInstance().generateShortUuid())
+                .discoveryName("discovery-" + 
UUIDUtils.getInstance().generateShortUuid())
+                .discoveryType("local")
+                .discoveryLevel("1")
+                .serverList("http://localhost:8080";)
+                .pluginName("divide")
+                .props("{}")
+                .namespaceId(SYS_DEFAULT_NAMESPACE_ID)
+                .dateCreated(now)
+                .dateUpdated(now)
+                .build();
+    }
+}
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryServiceImplTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryServiceImplTest.java
new file mode 100644
index 0000000000..060d490cb7
--- /dev/null
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryServiceImplTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.service;
+
+import org.apache.shenyu.admin.discovery.DiscoveryProcessor;
+import org.apache.shenyu.admin.discovery.DiscoveryProcessorHolder;
+import org.apache.shenyu.admin.mapper.DiscoveryHandlerMapper;
+import org.apache.shenyu.admin.mapper.DiscoveryMapper;
+import org.apache.shenyu.admin.mapper.DiscoveryRelMapper;
+import org.apache.shenyu.admin.mapper.ProxySelectorMapper;
+import org.apache.shenyu.admin.mapper.SelectorMapper;
+import org.apache.shenyu.admin.model.entity.DiscoveryDO;
+import org.apache.shenyu.admin.service.impl.DiscoveryServiceImpl;
+import org.apache.shenyu.admin.utils.ShenyuResultMessage;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+import java.util.Collections;
+
+import static 
org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test cases for DiscoveryServiceImpl.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public final class DiscoveryServiceImplTest {
+
+    @Mock
+    private DiscoveryMapper discoveryMapper;
+
+    @Mock
+    private ProxySelectorMapper proxySelectorMapper;
+
+    @Mock
+    private DiscoveryRelMapper discoveryRelMapper;
+
+    @Mock
+    private DiscoveryHandlerMapper discoveryHandlerMapper;
+
+    @Mock
+    private SelectorService selectorService;
+
+    @Mock
+    private SelectorMapper selectorMapper;
+
+    @Mock
+    private DiscoveryProcessorHolder discoveryProcessorHolder;
+
+    @Mock
+    private DiscoveryProcessor discoveryProcessor;
+
+    private DiscoveryServiceImpl discoveryService;
+
+    @BeforeEach
+    public void setUp() {
+        discoveryService = new DiscoveryServiceImpl(discoveryMapper, 
proxySelectorMapper, discoveryRelMapper,
+                discoveryHandlerMapper, selectorService, selectorMapper, 
discoveryProcessorHolder);
+        
given(discoveryProcessorHolder.chooseProcessor(anyString())).willReturn(discoveryProcessor);
+    }
+
+    @Test
+    public void testDelete() {
+        DiscoveryDO discoveryDO = DiscoveryDO.builder()
+                .id("discovery-1")
+                .discoveryType("local")
+                .namespaceId(SYS_DEFAULT_NAMESPACE_ID)
+                .build();
+        
given(discoveryHandlerMapper.selectByDiscoveryId("discovery-1")).willReturn(Collections.emptyList());
+        
given(discoveryMapper.selectById("discovery-1")).willReturn(discoveryDO);
+        given(discoveryMapper.delete("discovery-1", 
SYS_DEFAULT_NAMESPACE_ID)).willReturn(1);
+
+        assertEquals(ShenyuResultMessage.DELETE_SUCCESS, 
discoveryService.delete("discovery-1", SYS_DEFAULT_NAMESPACE_ID));
+        verify(discoveryProcessor).removeDiscovery(discoveryDO);
+        verify(discoveryMapper).delete("discovery-1", 
SYS_DEFAULT_NAMESPACE_ID);
+    }
+
+    @Test
+    public void testDeleteWithMismatchedNamespace() {
+        DiscoveryDO discoveryDO = DiscoveryDO.builder()
+                .id("discovery-1")
+                .discoveryType("local")
+                .namespaceId("another-namespace-id")
+                .build();
+        
given(discoveryHandlerMapper.selectByDiscoveryId("discovery-1")).willReturn(Collections.emptyList());
+        
given(discoveryMapper.selectById("discovery-1")).willReturn(discoveryDO);
+
+        assertThrows(ShenyuException.class, () -> 
discoveryService.delete("discovery-1", SYS_DEFAULT_NAMESPACE_ID));
+        verify(discoveryMapper, never()).delete(any(), any());
+        verify(discoveryProcessor, never()).removeDiscovery(any());
+    }
+
+    @Test
+    public void testDeleteWithDiscoveryNotFound() {
+        
given(discoveryHandlerMapper.selectByDiscoveryId("discovery-1")).willReturn(Collections.emptyList());
+        given(discoveryMapper.selectById("discovery-1")).willReturn(null);
+
+        assertThrows(ShenyuException.class, () -> 
discoveryService.delete("discovery-1", SYS_DEFAULT_NAMESPACE_ID));
+        verify(discoveryMapper, never()).delete(any(), any());
+        verify(discoveryProcessor, never()).removeDiscovery(any());
+    }
+}

Reply via email to