@Override
    public final void unsubscribe(URL url, NotifyListener listener) {
        if (!shouldSubscribe(url)) { // Should Not Subscribe
            return;
        }
        url = addRegistryClusterKey(url);
        doUnsubscribe(url, listener);
    }
@Test
    void testUnsubscribe() {
        // do subscribe to prepare for unsubscribe verification
        Set<String> multiApps = new TreeSet<>();
        multiApps.add(APP_NAME1);
        multiApps.add(APP_NAME2);
        NotifyListener testServiceListener2 = mock(NotifyListener.class);
        URL url2 = URL.valueOf("consumer://127.0.0.1/TestService2?interface=TestService1&check=false&protocol=tri");
        when(testServiceListener2.getConsumerUrl()).thenReturn(url2);
        serviceDiscoveryRegistry.subscribeURLs(url, testServiceListener, multiApps);
        serviceDiscoveryRegistry.subscribeURLs(url2, testServiceListener2, multiApps);
        assertEquals(1, serviceDiscoveryRegistry.getServiceListeners().size());

        // do unsubscribe
        when(mapping.getMapping(url2)).thenReturn(multiApps);
        serviceDiscoveryRegistry.doUnsubscribe(url2, testServiceListener2);
        assertEquals(1, serviceDiscoveryRegistry.getServiceListeners().size());
        ServiceInstancesChangedListener instancesChangedListener = serviceDiscoveryRegistry
                .getServiceListeners()
                .entrySet()
                .iterator()
                .next()
                .getValue();
        assertTrue(instancesChangedListener.hasListeners());
        when(mapping.getMapping(url)).thenReturn(multiApps);
        serviceDiscoveryRegistry.doUnsubscribe(url, testServiceListener);
        assertEquals(0, serviceDiscoveryRegistry.getServiceListeners().size());
        assertFalse(instancesChangedListener.hasListeners());
    }