diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2014-01-24 00:55:25 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2014-01-24 00:55:25 +0100 |
commit | d65773c6bf2ac93ae6081297fa130eca85fe9e91 (patch) | |
tree | 24eaabcd9a069633fab38ffa4a4ab5d9a037a279 /sonar-testing-harness | |
parent | 078cff8c82b9b3f4bb31f6c014d0bb96f7a1b46a (diff) | |
download | sonarqube-d65773c6bf2ac93ae6081297fa130eca85fe9e91.tar.gz sonarqube-d65773c6bf2ac93ae6081297fa130eca85fe9e91.zip |
SONAR-5010 improve testability of web service and fix media type of response
Diffstat (limited to 'sonar-testing-harness')
-rw-r--r-- | sonar-testing-harness/pom.xml | 30 | ||||
-rw-r--r-- | sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java | 216 |
2 files changed, 233 insertions, 13 deletions
diff --git a/sonar-testing-harness/pom.xml b/sonar-testing-harness/pom.xml index 777d2790c72..e32a3a72f43 100644 --- a/sonar-testing-harness/pom.xml +++ b/sonar-testing-harness/pom.xml @@ -13,42 +13,46 @@ <dependencies> <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> + <groupId>org.easytesting</groupId> + <artifactId>fest-assert</artifactId> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> </dependency> <dependency> - <groupId>org.easytesting</groupId> - <artifactId>fest-assert</artifactId> + <groupId>org.skyscreamer</groupId> + <artifactId>jsonassert</artifactId> </dependency> <dependency> - <groupId>xmlunit</groupId> - <artifactId>xmlunit</artifactId> + <groupId>com.google.code.findbugs</groupId> + <artifactId>jsr305</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> </dependency> <dependency> + <!-- used only for org.sonar.test.channel classes --> <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-plugin-api</artifactId> + <artifactId>sonar-channel</artifactId> <version>${project.version}</version> + <optional>true</optional> </dependency> <dependency> <groupId>org.codehaus.sonar</groupId> <artifactId>sonar-plugin-api</artifactId> <version>${project.version}</version> - <type>test-jar</type> </dependency> <dependency> - <!-- used only for org.sonar.test.channel classes --> <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-channel</artifactId> + <artifactId>sonar-plugin-api</artifactId> <version>${project.version}</version> - <optional>true</optional> + <type>test-jar</type> </dependency> <dependency> - <groupId>com.google.code.findbugs</groupId> - <artifactId>jsr305</artifactId> + <groupId>xmlunit</groupId> + <artifactId>xmlunit</artifactId> </dependency> </dependencies> </project> diff --git a/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java b/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java new file mode 100644 index 00000000000..aad0844ea5c --- /dev/null +++ b/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java @@ -0,0 +1,216 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.server.ws; + +import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; +import org.skyscreamer.jsonassert.JSONAssert; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.utils.text.XmlWriter; + +import javax.annotation.CheckForNull; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * @since 4.2 + */ +public class WsTester { + + public static class TestRequest extends Request { + + private final WebService.Controller controller; + private final String actionKey; + private String method = "GET"; + private Map<String, String> params = new HashMap<String, String>(); + + private TestRequest(WebService.Controller controller, String actionKey) { + this.controller = controller; + this.actionKey = actionKey; + } + + @Override + public String method() { + return method; + } + + public TestRequest setMethod(String s) { + this.method = s; + return this; + } + + public TestRequest setParams(Map<String, String> m) { + this.params = m; + return this; + } + + public TestRequest setParam(String key, @CheckForNull String value) { + if (value != null) { + params.put(key, value); + } + return this; + } + + @Override + @CheckForNull + public String param(String key) { + return params.get(key); + } + + public Result execute() throws Exception { + WebService.Action action = controller.action(actionKey); + if (action == null) { + throw new IllegalArgumentException("Action not found: " + actionKey); + } + TestResponse response = new TestResponse(); + action.handler().handle(this, response); + return new Result(response); + } + } + + public static class TestResponse implements Response { + + public class TestStream implements Response.Stream { + private String mediaType; + + @CheckForNull + public String mediaType() { + return mediaType; + } + + @Override + public Response.Stream setMediaType(String s) { + this.mediaType = s; + return this; + } + + @Override + public OutputStream output() { + return output; + } + } + + private int status = 200; + private final ByteArrayOutputStream output = new ByteArrayOutputStream(); + + @Override + public JsonWriter newJsonWriter() { + return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8)); + } + + @Override + public XmlWriter newXmlWriter() { + return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8)); + } + + @Override + public Stream stream() { + return new TestStream(); + } + + @Override + public int status() { + return status; + } + + @Override + public Response setStatus(int httpStatus) { + this.status = httpStatus; + return this; + } + } + + + public static class Result { + private final TestResponse response; + + private Result(TestResponse response) { + this.response = response; + } + + public Result assertStatus(int httpStatus) { + assertThat(httpStatus).isEqualTo(response.status()); + return this; + } + + public String outputAsString() { + return new String(response.output.toByteArray(), Charsets.UTF_8); + } + + public Result assertJson(String expectedJson) throws Exception { + String json = outputAsString(); + JSONAssert.assertEquals(expectedJson, json, true); + return this; + } + + /** + * Compares JSON response with JSON file available in classpath. For example if class + * is org.foo.BarTest and filename is index.json, then file must be located + * at src/test/resources/org/foo/BarTest/index.json. + * + * @param clazz the test class + * @param jsonResourceFilename name of the file containing the expected JSON + */ + public Result assertJson(Class clazz, String expectedJsonFilename) throws Exception { + String path = clazz.getSimpleName() + "/" + expectedJsonFilename; + URL url = clazz.getResource(path); + if (url == null) { + throw new IllegalStateException("Cannot find " + path); + } + String json = outputAsString(); + JSONAssert.assertEquals(IOUtils.toString(url), json, true); + return this; + } + } + + private final WebService.Context context = new WebService.Context(); + + public WsTester(WebService... webServices) { + for (WebService webService : webServices) { + webService.define(context); + } + } + + public WebService.Context context() { + return context; + } + + @CheckForNull + public WebService.Controller controller(String path) { + return context.controller(path); + } + + public TestRequest newRequest(String actionKey) { + if (context.controllers().size() != 1) { + throw new IllegalStateException("The method newRequest(String) requires to define one, and only one, controller"); + } + return new TestRequest(context.controllers().get(0), actionKey); + } + + public TestRequest newRequest(String controllerPath, String actionKey) { + return new TestRequest(context.controller(controllerPath), actionKey); + } +} |