【问题标题】:Unit testing Java Spark microframework单元测试 Java Spark 微框架
【发布时间】:2017-02-23 11:23:27
【问题描述】:

我正在尝试向 java 微服务添加一个 restful api。为此,我正在使用 spark:

http://sparkjava.com/documentation.html

我创建了一个非常简单的类,它支持一个 api。那堂课在这里:

public class Routes {
    public void establishRoutes(){
        get("/test", (req, res) -> "Hello World");
        after((req, res) -> {
            res.type("application/json");
        });

        exception(IllegalArgumentException.class, (e, req, res) -> {
            res.status(400);
        });
    }

现在,运行 Routes.establishRoutes() 应该会建立一个 api,如果有人决定访问 http://localhost:4567/test,它将显示“Hello World”。这确实有效。万岁!

下一步是对代码进行单元测试。不幸的是,我的单元测试没有成功。 spark 文档没有详细说明进行测试的合理方法,因此我所拥有的内容是从我在网上找到的示例拼凑而成的。这是我的 Junit 测试:

public class TestRoutes {
        @Before
        public void setUp() throws Exception {
            Routes newRoutes = new Routes();
            newRoutes.establishRoutes();
        }

        @After
        public void tearDown() throws Exception {
            stop();
        }

        @Test
        public void testModelObjectsPOST(){

            String testUrl = "/test";


            ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
            Map<String, String> json = res.json();
            assertEquals(201, res.status);
        }

下面是 ApiTestUtils.request() 背后的代码:

public class ApiTestUtils {
    public static TestResponse request(String method, String path, String requestBody) {


        try {
            URL url = new URL("http://localhost:4567" + path);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod(method);
            connection.setDoOutput(true);
            connection.connect();
            String body = IOUtils.toString(connection.getInputStream());
            return new TestResponse(connection.getResponseCode(), body);
        } catch (IOException e) {
            e.printStackTrace();
            fail("Sending request failed: " + e.getMessage());
            return null;
        }
    }

    public static class TestResponse {

        public final String body;
        public final int status;

        public TestResponse(int status, String body) {
            this.status = status;
            this.body = body;
        }

        public Map<String,String> json() {
            return new Gson().fromJson(body, HashMap.class);
        }
    }
}

我在ApiTestUtils.request() 内的connection.connect() 上失败了。具体来说,我得到了错误:java.lang.AssertionError: Sending request failed: Connection refused

我相信这是因为当我的测试尝试发出请求时应用程序没有监听。但是,我不明白为什么会这样。我从这里找到的演示项目中借用了测试代码: https://github.com/mscharhag/blog-examples/blob/master/sparkdemo/src/test/java/com/mscharhag/sparkdemo/UserControllerIntegrationTest.java

更新: 我尝试运行上面链接的示例。事实证明,它也不起作用。看起来在这种情况下启动一个 spark 实例比我想象的更困难?我不是想弄清楚该怎么做。

【问题讨论】:

  • 您应该阅读单元测试和集成测试之间的区别。你试图用该代码做的是后者。例如,单元测试会在 Test 方法中直接调用 establishRoutes 并验证返回值或副作用。
  • 很公平。你觉得junit不适合做集成测试吗?
  • Junit 可以。不过,您必须确保启动服务器。它不喜欢你在任何地方都这样做。看例子Main的使用
  • 我也是这么想的。但是,示例中的Main 方法似乎没有做我在Routes.establishRoutes() 中没有做的任何事情。您是否观察到我未能采取的方法调用或正在采取的行动?

标签: java rest unit-testing junit spark-java


【解决方案1】:

在您的测试用例中缺少用于等待嵌入式服务器初始化的代码。 我已经尝试了您的代码,并偶然发现了与您相同的问题,但是在调试之后我注意到嵌入式 Spark 服务器是在新创建的线程中初始化的。 (见方法spark.Service#init())。 在你的测试中你需要做的就是通过调用spark.Spark#awaitInitialization()方法等待初始化

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static junit.framework.TestCase.assertEquals;
import static spark.Spark.awaitInitialization;
import static spark.Spark.stop;

public class TestRoutes {
    @Before
    public void setUp() throws Exception {
        Routes newRoutes = new Routes();
        newRoutes.establishRoutes();

        awaitInitialization();

    }

    @After
    public void tearDown() throws Exception {
        stop();
    }

    @Test
    public void testModelObjectsPOST() {

        String testUrl = "/test";


        ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
        assertEquals(200, res.status);
    }

}

【讨论】:

    【解决方案2】:

    我无法帮助您使用 Spark,但如果您愿意尝试使用替代的轻量级 Java 库来编写微服务,请查看 Molecule

    您将找到用于编写单元测试和集成测试的文档和示例。如果我理解您要正确测试的内容,测试将如下所示:

    HttpRequest request = new HttpRequest(4567);
    HttpResponse response = request.get("/test");
    assertThat(response).hasStatusCode(201)
                        .hasContentType("application/json")
                        .hasBodyText("Hello World");
    

    【讨论】:

      猜你喜欢
      • 2010-09-10
      • 2023-04-10
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      相关资源
      最近更新 更多