<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have searched the <a href="https://github.com/apache/incubator-dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/apache/incubator-dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Dubbo version: xxx</li>
<li>Operating System version: xxx</li>
<li>Java version: xxx</li>
</ul>
<h3 dir="auto">Steps to reproduce this issue</h3>
<p dir="auto">nacos registry serviceName may conflict when we have two provider with same service but one config version as A and left group empty and<br>
one config group as A and left version empty</p>
<p dir="auto">the two provider would get registered with same key    provdier:serviceName:A.</p>
<p dir="auto">the cause of this issue is we ignore empty value when we construct the key,  relative code is</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" private String getServiceName(URL url) {
        String category = url.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY);
        return getServiceName(url, category);
    }

    private String getServiceName(URL url, String category) {
        StringBuilder serviceNameBuilder = new StringBuilder(category);
        append(serviceNameBuilder, url, INTERFACE_KEY);
        append(serviceNameBuilder, url, VERSION_KEY);
        append(serviceNameBuilder, url, GROUP_KEY);
        return serviceNameBuilder.toString();
    }

private void append(StringBuilder target, URL url, String parameterName) {
        target.append(SERVICE_NAME_SEPARATOR);
        String parameterValue = url.getParameter(parameterName);
        if (!StringUtils.isBlank(parameterValue)) {
            target.append(parameterValue);
        }
    }"><pre class="notranslate"> <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">getServiceName</span>(<span class="pl-smi">URL</span> <span class="pl-s1">url</span>) {
        <span class="pl-smi">String</span> <span class="pl-s1">category</span> = <span class="pl-s1">url</span>.<span class="pl-en">getParameter</span>(<span class="pl-c1">CATEGORY_KEY</span>, <span class="pl-c1">DEFAULT_CATEGORY</span>);
        <span class="pl-k">return</span> <span class="pl-en">getServiceName</span>(<span class="pl-s1">url</span>, <span class="pl-s1">category</span>);
    }

    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">getServiceName</span>(<span class="pl-smi">URL</span> <span class="pl-s1">url</span>, <span class="pl-smi">String</span> <span class="pl-s1">category</span>) {
        <span class="pl-smi">StringBuilder</span> <span class="pl-s1">serviceNameBuilder</span> = <span class="pl-k">new</span> <span class="pl-smi">StringBuilder</span>(<span class="pl-s1">category</span>);
        <span class="pl-en">append</span>(<span class="pl-s1">serviceNameBuilder</span>, <span class="pl-s1">url</span>, <span class="pl-c1">INTERFACE_KEY</span>);
        <span class="pl-en">append</span>(<span class="pl-s1">serviceNameBuilder</span>, <span class="pl-s1">url</span>, <span class="pl-c1">VERSION_KEY</span>);
        <span class="pl-en">append</span>(<span class="pl-s1">serviceNameBuilder</span>, <span class="pl-s1">url</span>, <span class="pl-c1">GROUP_KEY</span>);
        <span class="pl-k">return</span> <span class="pl-s1">serviceNameBuilder</span>.<span class="pl-en">toString</span>();
    }

<span class="pl-k">private</span> <span class="pl-smi">void</span> <span class="pl-s1">append</span>(<span class="pl-smi">StringBuilder</span> <span class="pl-s1">target</span>, <span class="pl-smi">URL</span> <span class="pl-s1">url</span>, <span class="pl-smi">String</span> <span class="pl-s1">parameterName</span>) {
        <span class="pl-s1">target</span>.<span class="pl-en">append</span>(<span class="pl-c1">SERVICE_NAME_SEPARATOR</span>);
        <span class="pl-smi">String</span> <span class="pl-s1">parameterValue</span> = <span class="pl-s1">url</span>.<span class="pl-en">getParameter</span>(<span class="pl-s1">parameterName</span>);
        <span class="pl-k">if</span> (!<span class="pl-smi">StringUtils</span>.<span class="pl-en">isBlank</span>(<span class="pl-s1">parameterValue</span>)) {
            <span class="pl-s1">target</span>.<span class="pl-en">append</span>(<span class="pl-s1">parameterValue</span>);
        }
    }</pre></div>
<p dir="auto">i think we should just keep a SEPARATOR as placeholder for empty value.</p>
<ol dir="auto">
<li>xxx</li>
<li>xxx</li>
<li>xxx</li>
</ol>
<p dir="auto">Pls. provide [GitHub address] to reproduce this issue.</p>
<h3 dir="auto">Expected Result</h3>
<p dir="auto">What do you expected from the above steps？</p>
<h3 dir="auto">Actual Result</h3>
<p dir="auto">What actually happens?</p>
<p dir="auto">If there is an exception, please attach the exception trace:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Just put your stack trace here!"><pre class="notranslate"><code class="notranslate">Just put your stack trace here!
</code></pre></div>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/apache/dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/apache/dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h3 dir="auto">General Description</h3>
<p dir="auto">I noticed that there are many test to production inheritance structure in test code. Maybe it is not the best practice for test design. I suggest that we can use existing mock framework to refactor these structures.</p>
<h3 dir="auto">Refactor Goal</h3>
<p dir="auto">Increase the readability for test code and decrease the coupling between test and production code.</p>
<p dir="auto">The child test class that inherit production class will be removed after refactoring, relevant dependencies will be replaced by mocking framework.</p>