简体   繁体   English

Spark Web框架单元测试

[英]Spark web framework unit tests

I am working with the Spark web framework and creating a RESTful API . 我正在使用Spark Web框架并创建RESTful API ( http://sparkjava.com since there are multiple things out there named "Spark") http://sparkjava.com因为有很多东西叫做“Spark”)

My employer's standards mandate that we write a series of unit tests that will be automatically run once a day to confirm that applications are still up. 我的雇主的标准要求我们编写一系列单元测试,每天自动运行一次,以确认应用程序仍在运行。

Spark is easy to test myself using a tool like Postman but I have not found any good examples of JUnit tests being written with Spark or even with HTTP Requests being made programmatically with it. Spark很容易使用像Postman这样的工具来测试自己,但是我没有找到任何使用Spark编写的JUnit测试的好例子,甚至是用编程方式编写的HTTP请求

Has anyone done this before? 有没有人这样做过? Is it possible? 可能吗?

we have develop a small library that facilitates the unit testing of Spark controllers/endpoints. 我们开发了一个小型库,便于Spark控制器/端点的单元测试。

Github Github上

Also, the version 1.1.3 is published in Maven Central Repository 此外,版本1.1.3发布在Maven Central Repository中

<dependency>
        <groupId>com.despegar</groupId>
        <artifactId>spark-test</artifactId>
        <version>1.1.3</version>
        <scope>test</scope>
    </dependency>

I had the same requirement that you and I found a way to make it work. 我有同样的要求,你和我找到了让它运作的方法。 I searched over Spark source code and I found two classes that are useful: 我搜索了Spark源代码,发现了两个有用的类:

  • SparkTestUtil : this class wraps Apache HttpClient and expose methods to make different http requests against a local web server (running in localhost) with customizable port (in constructor) and relative path (in requests methods) SparkTestUtil :此类包装Apache HttpClient并公开方法,以使用可自定义的端口(在构造函数中)和相对路径(在请求方法中)对本地Web服务器(在localhost中运行)发出不同的http请求
  • ServletTest : it starts a Jetty instance in a local port with an application context and a relative directory path where a WEB-INF/web.xml file descriptor can be found. ServletTest :它在本地端口中启动Jetty实例,其中包含应用程序上下文和相对目录路径,可以在其中找到WEB-INF / web.xml文件描述符。 This web.xml will be use to simulate a web application. 此web.xml将用于模拟Web应用程序。 Then it uses SparkTestUtil to make http requests against this simulated application and assert results. 然后,它使用SparkTestUtil对此模拟应用程序发出http请求并声明结果。

This is what I did: I created a junit test class that implements SparkApplication interface. 这就是我所做的:我创建了一个实现SparkApplication接口的junit测试类。 In that interface I create and initialize the "controller" (a class of my application) in charge of answer http requests. 在该接口中,我创建并初始化负责回答http请求的“控制器”(我的应用程序类)。 In a method annotated with @BeforeClass I initialize the Jetty instance using a web.xml that refers to the junit test class as the SparkApplication and a SparkTestUtil 在使用@BeforeClass注释的方法中,我使用web.xml初始化Jetty实例,该文件将junit测试类称为SparkApplication和SparkTestUtil

JUnit test class JUnit测试类

package com.test

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.webapp.WebAppContext;

public class ControllerTest implements SparkApplication {

    private static SparkTestUtil sparkTestUtil;

    private static Server webServer;

    @Override
    public void init() {
         new Controller(...)
    }

    @BeforeClass
    public static void beforeClass() throws Exception {
       sparkTestUtil = new SparkTestUtil(PORT);
       webServer = new Server();
       ServerConnector connector = new ServerConnector(webServer);
       connector.setPort(PORT);
       webServer.setConnectors(new Connector[] {connector});
       WebAppContext bb = new WebAppContext();
       bb.setServer(webServer);
       bb.setContextPath("/");
       bb.setWar("src/test/webapp/");
       webServer.setHandler(bb);
       webServer.start();
       (...)
    }

    @AfterClass
    public static void afterClass() throws Exception {
       webServer.stop();
       (...)
    }    

}

src/test/webapp/WEB-INF/web.xml file src / test / webapp / WEB-INF / web.xml文件

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <filter>
        <filter-name>SparkFilter</filter-name>
        <filter-class>spark.servlet.SparkFilter</filter-class>
        <init-param>
            <param-name>applicationClass</param-name>
            <param-value>com.test.ControllerTest</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>SparkFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

This can be improved, but it is a good starting point I think. 这可以改进,但我认为这是一个很好的起点。 Maybe some "spark-test" component could be created? 也许可以创建一些“火花测试”组件?

Hope this would be useful for you! 希望这对你有用!

Here is my Solution.You just need additional add apache-http and junit dependency. 这是我的解决方案。您只需要额外添加apache-http和junit依赖项。

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

public class SparkServer {
    public static void main(String[] args) {
        Spark.port(8888);
        Spark.threadPool(1000, 1000,60000);
        Spark.get("/ping", (req, res) -> "pong");
    }
}

public class SparkTest {
    @Before
    public void setup() {
        SparkServer.main(null);
    }
    @After
    public void tearDown() throws Exception {
        Thread.sleep(1000);
        Spark.stop();
    }
    @Test
    public void test() throws IOException {

        CloseableHttpClient httpClient = HttpClients.custom()
                .build();

        HttpGet httpGet = new HttpGet("http://localhost:8888/ping");
        CloseableHttpResponse response = httpClient.execute(httpGet);

        int statusCode = response.getStatusLine().getStatusCode();
        BufferedReader rd = new BufferedReader(
                 new InputStreamReader(response.getEntity().getContent()));

        StringBuffer result = new StringBuffer();
        String line = "";
        while ((line = rd.readLine()) != null) {
            result.append(line);
        }

        assertEquals(200, statusCode);
        assertEquals("pong", result.toString());
    }
}

Another approach wis to create a class which implements Route in each path or route . 另一种方法是创建一个在每个pathroute实现Route的类。 For example, if you have a route like next: 例如,如果您有下一条路线:

get("maintenance/task", (req, response) -> {....}); 

Then replace (req, response) -> {....} lambda by a class implementing Route . 然后用实现Route的类替换(req, response) -> {....} lambda。

For example: 例如:

public class YourRoute implements Route {
   public Object handle(Request request, Response response) throws Exception {
     ....
   }
}

Would be: 将会:

get("maintenance/task", new YourRoute()); 

Then you can unit testing YourRoute class using JUnit. 然后,您可以使用JUnit对YourRoute类进行单元测试。


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Spock 框架运行 Android 单元测试 - Running Android unit tests with Spock framework 从带有简单参数的单元测试中调用主(spark)应用程序 - Invoke a main (spark) application from unit tests with simple parameters jenkins上的机器人框架测试中的Web驱动程序异常 - Web driver exception on robot framework tests on jenkins XMLType(oracle),带有内存HSQL数据库和Spring框架的单元测试 - XMLType (oracle), unit tests with in memory HSQL database and Spring framework Play Framework 2(Java)中的单元测试不会回滚测试之间的更改 - Unit test in Play Framework 2 (Java) not rolling back changes between tests 如何使用Spock框架编写多个单元测试? - How do I write multiple unit tests using Spock framework? 在Intellij IDEA 13中播放框架2运行单元测试 - Play framework 2 running unit tests in Intellij IDEA 13 播放框架在内存h2数据库中用于单元测试 - play framework use in memory h2 database for unit tests 如何在 intellij 中为 play 框架应用程序运行单元测试 - how to run unit tests for a play framework application within intellij 如何在Play框架单元测试中加载不同的插件? - How to load different plugins in Play framework unit tests?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM