add more integration test (#261)

* add more integration test

* fix test failure

* fix test failure
diff --git a/dubbo-admin-backend/pom.xml b/dubbo-admin-backend/pom.xml
index 3c9dbd9..be5a69c 100644
--- a/dubbo-admin-backend/pom.xml
+++ b/dubbo-admin-backend/pom.xml
@@ -32,6 +32,7 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
+        <mockito-version>2.23.4</mockito-version>
     </properties>
 
     <dependencies>
@@ -119,6 +120,12 @@
             <groupId>io.netty</groupId>
             <artifactId>netty-all</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito-version}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index ef2ef89..6bd38ca 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -54,6 +54,7 @@
     public static final String CONSUMERS_CATEGORY = "consumers";
     public static final String SPECIFICATION_VERSION_KEY = "release";
     public static final String GLOBAL_CONFIG = "global";
+    public static final String GLOBAL_CONFIG_PATH = "config/dubbo/dubbo.properties";
     public static final Set<String> CONFIGS = new HashSet<>();
 
     static {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
index c846ce6..22a638e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
@@ -72,7 +72,7 @@
         List<ConfigDTO> configDTOs = new ArrayList<>();
         if (key.equals(Constants.ANY_VALUE)) {
             query = providerService.findApplications();
-            query.add("global");
+            query.add(Constants.GLOBAL_CONFIG);
         } else {
             query.add(key);
         }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
index d43e6de..a1668fd 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
@@ -22,16 +22,14 @@
 import org.apache.dubbo.admin.service.ManagementService;
 import org.springframework.stereotype.Component;
 
+import static org.apache.dubbo.admin.common.util.Constants.GLOBAL_CONFIG_PATH;
+
 @Component
 public class ManagementServiceImpl extends AbstractService implements ManagementService {
-
-
-    private static String globalConfigPath = "config/dubbo/dubbo.properties";
-
     @Override
     public void setConfig(ConfigDTO config) {
         if (Constants.GLOBAL_CONFIG.equals(config.getKey())) {
-            dynamicConfiguration.setConfig(globalConfigPath, config.getConfig());
+            dynamicConfiguration.setConfig(GLOBAL_CONFIG_PATH, config.getConfig());
         } else {
             dynamicConfiguration.setConfig(getPath(config.getKey()), config.getConfig());
         }
@@ -40,7 +38,7 @@
     @Override
     public String getConfig(String key) {
         if (Constants.GLOBAL_CONFIG.equals(key)) {
-            return dynamicConfiguration.getConfig(globalConfigPath);
+            return dynamicConfiguration.getConfig(GLOBAL_CONFIG_PATH);
         }
         return dynamicConfiguration.getConfig(getPath(key));
     }
@@ -48,7 +46,7 @@
     @Override
     public String getConfigPath(String key) {
         if (Constants.GLOBAL_CONFIG.equals(key)) {
-            return dynamicConfiguration.getPath(globalConfigPath);
+            return dynamicConfiguration.getPath(GLOBAL_CONFIG_PATH);
         }
         return dynamicConfiguration.getPath(getPath(key));
     }
@@ -57,7 +55,7 @@
     public boolean updateConfig(ConfigDTO configDTO) {
         String key = configDTO.getKey();
         if (Constants.GLOBAL_CONFIG.equals(key)) {
-            dynamicConfiguration.setConfig(globalConfigPath, configDTO.getConfig());
+            dynamicConfiguration.setConfig(GLOBAL_CONFIG_PATH, configDTO.getConfig());
         } else {
             dynamicConfiguration.setConfig(getPath(key), configDTO.getConfig());
         }
@@ -67,7 +65,7 @@
     @Override
     public boolean deleteConfig(String key) {
         if (Constants.GLOBAL_CONFIG.equals(key)) {
-            dynamicConfiguration.deleteConfig(globalConfigPath);
+            dynamicConfiguration.deleteConfig(GLOBAL_CONFIG_PATH);
         } else {
             dynamicConfiguration.deleteConfig(getPath(key));
         }
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
index a151d3b..5640c30 100644
--- a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.dubbo.admin;
 
-import java.io.IOException;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.retry.RetryOneTime;
@@ -29,11 +28,13 @@
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.web.client.TestRestTemplate;
 import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.web.client.RestTemplate;
 
+import java.io.IOException;
+
 @ActiveProfiles("test")
-@RunWith(SpringRunner.class)
+@RunWith(SpringJUnit4ClassRunner.class)
 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 public abstract class AbstractSpringIntegrationTest {
   protected RestTemplate restTemplate = (new TestRestTemplate()).getRestTemplate();
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
new file mode 100644
index 0000000..5683df0
--- /dev/null
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.dubbo.admin.controller;
+
+import org.apache.dubbo.admin.AbstractSpringIntegrationTest;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.ConfigDTO;
+import org.apache.dubbo.admin.service.ProviderService;
+import org.junit.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+public class ManagementControllerTest extends AbstractSpringIntegrationTest {
+  private final String env = "whatever";
+
+  @MockBean
+  private ProviderService providerService;
+
+  @Test
+  public void shouldCreateGlobalConfig() throws Exception {
+    ConfigDTO configDTO = new ConfigDTO();
+    configDTO.setKey(Constants.GLOBAL_CONFIG);
+    configDTO.setConfig("key1=val1\nkey2=val2");
+    ResponseEntity<Boolean> responseEntity = restTemplate.postForEntity(
+        url("/api/{env}/manage/config"), configDTO, Boolean.class, env
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED);
+    assertEquals(responseEntity.getBody(), true);
+
+    byte[] bytes = zkClient.getData().forPath(getPath("dubbo"));
+    String config = new String(bytes);
+    assertEquals(configDTO.getConfig(), config);
+
+    zkClient.delete().forPath(getPath("dubbo"));
+  }
+
+  @Test
+  public void shouldCreateApplicationConfig() throws Exception {
+    String application = "dubbo-admin";
+    ConfigDTO configDTO = new ConfigDTO();
+    configDTO.setKey(application);
+    configDTO.setConfig("key1=val1\nkey2=val2");
+    ResponseEntity<Boolean> responseEntity = restTemplate.postForEntity(
+        url("/api/{env}/manage/config"), configDTO, Boolean.class, env
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED);
+    assertEquals(responseEntity.getBody(), true);
+
+    byte[] bytes = zkClient.getData().forPath(getPath(application));
+    String config = new String(bytes);
+    assertEquals(configDTO.getConfig(), config);
+  }
+
+  @Test
+  public void shouldThrowWhenUpdateNonExistedConfigKey() {
+    ConfigDTO configDTO = new ConfigDTO();
+    configDTO.setKey(Constants.GLOBAL_CONFIG);
+    configDTO.setConfig("key1=val1\nkey2=val2");
+    ResponseEntity<Void> responseEntity = restTemplate.exchange(
+        url("/api/{env}/manage/config/{key}"), HttpMethod.PUT,
+        new HttpEntity<>(configDTO), Void.class, env, "non-existed"
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.NOT_FOUND);
+  }
+
+  @Test
+  public void shouldUpdateConfigSpecifiedKey() throws Exception {
+    String key = "shouldUpdateConfigSpecifiedKey";
+    ConfigDTO configDTO = new ConfigDTO();
+    configDTO.setKey(key);
+    configDTO.setConfig("key1=val1\nkey2=val2");
+    restTemplate.postForEntity(url("/api/{env}/manage/config"), configDTO, Boolean.class, env);
+
+    configDTO.setConfig("key1=updatedVal1\nkey2=updatedVal2");
+    ResponseEntity<Void> responseEntity = restTemplate.exchange(
+        url("/api/{env}/manage/config/{key}"), HttpMethod.PUT,
+        new HttpEntity<>(configDTO), Void.class, env, key
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
+
+    byte[] bytes = zkClient.getData().forPath(getPath(key));
+    String config = new String(bytes);
+    assertEquals("key1=updatedVal1\nkey2=updatedVal2", config);
+  }
+
+  @Test
+  public void shouldGetAllConfig() throws Exception {
+    int num = 20;
+    List<ConfigDTO> configDTOs = new ArrayList<>(num);
+    for (int i = 0; i < num; i++) {
+      ConfigDTO configDTO = new ConfigDTO();
+      configDTO.setKey("key" + i);
+      configDTO.setConfig("key1=val1\nkey2=val2");
+      configDTOs.add(configDTO);
+
+      String path = getPath(configDTO.getKey());
+      if (zkClient.checkExists().forPath(path) == null) {
+        zkClient.create().creatingParentsIfNeeded().forPath(path);
+      }
+      zkClient.setData().forPath(path, configDTO.getConfig().getBytes());
+    }
+    when(providerService.findApplications())
+        .thenReturn(configDTOs.stream().map(ConfigDTO::getKey).collect(Collectors.toSet()));
+
+    ResponseEntity<List<ConfigDTO>> responseEntity = restTemplate.exchange(
+        url("/api/{env}/manage/config/{key}"), HttpMethod.GET,
+        null, new ParameterizedTypeReference<List<ConfigDTO>>() {
+        }, env, "*"
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
+    assertThat(responseEntity.getBody(), hasSize(num));
+  }
+
+  @Test
+  public void shouldDeleteConfig() throws Exception {
+    int num = 20;
+    List<ConfigDTO> configDTOs = new ArrayList<>(num);
+    for (int i = 0; i < num; i++) {
+      ConfigDTO configDTO = new ConfigDTO();
+      configDTO.setKey("shouldDeleteConfigKey" + i);
+      configDTO.setConfig("key1=val1\nkey2=val2");
+      configDTOs.add(configDTO);
+
+      String path = getPath(configDTO.getKey());
+      if (zkClient.checkExists().forPath(path) == null) {
+        zkClient.create().creatingParentsIfNeeded().forPath(path);
+      }
+      zkClient.setData().forPath(path, configDTO.getConfig().getBytes());
+    }
+    when(providerService.findApplications())
+        .thenReturn(configDTOs.stream().map(ConfigDTO::getKey).collect(Collectors.toSet()));
+
+    restTemplate.delete(url("/api/{env}/manage/config/{key}"), env, "shouldDeleteConfigKey1");
+    ResponseEntity<List<ConfigDTO>> responseEntity = restTemplate.exchange(
+        url("/api/{env}/manage/config/{key}"), HttpMethod.GET,
+        null, new ParameterizedTypeReference<List<ConfigDTO>>() {
+        }, env, "*"
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
+    assertThat(responseEntity.getBody(), hasSize(num - 1));
+
+    restTemplate.delete(url("/api/{env}/manage/config/{key}"), env, "shouldDeleteConfigKey10");
+    responseEntity = restTemplate.exchange(
+        url("/api/{env}/manage/config/{key}"), HttpMethod.GET,
+        null, new ParameterizedTypeReference<List<ConfigDTO>>() {
+        }, env, "*"
+    );
+    assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
+    assertThat(responseEntity.getBody(), hasSize(num - 2));
+  }
+
+  private String getPath(String key) {
+    return "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR
+        + Constants.DUBBO_PROPERTY;
+  }
+}
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ServiceControllerTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ServiceControllerTest.java
index 7518675..ba5f41b 100644
--- a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ServiceControllerTest.java
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/controller/ServiceControllerTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.dubbo.admin.controller;
 
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
 import org.apache.dubbo.admin.AbstractSpringIntegrationTest;
 import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.ServiceDTO;
@@ -32,6 +30,10 @@
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
@@ -41,7 +43,7 @@
   private Registry registry;
 
   @Before
-  public void setUp() throws InterruptedException {
+  public void setUp() throws Exception {
     final Set<URL> registered = ((AbstractRegistry) registry).getRegistered();
     for (final URL url : registered) {
       registry.unregister(url);