【问题标题】:Host website during integration test在集成测试期间托管网站
【发布时间】:2017-07-15 22:27:05
【问题描述】:

我正在开发一个抓取工具,我正在尝试编写一个集成测试来抓取存储在磁盘上的 HTML。测试应该从 img src 抓取图像 url。在代码中,这归结为Jsoup.connect(url),其中 url 是一个字符串。我知道模拟,但这不属于集成测试。这就是我认为托管网站并真正返回图像的原因。当然也欢迎其他选择。

理想情况下,在测试运行时启动一个占用空间小的 Web 服务器。我应该能够确定或至少知道它发布网站的网址。我还应该能够将 Web 服务器指向一个 HTML 文件。

爬虫项目是一个 Spring Boot。我可以静态地提供页面,就像从 /static 中一样,而不是由控制器解决。当我有一个控制器返回页面时,它由 Thymeleaf 解决并抛出org.xml.sax.SAXParseException: The entity name must immediately follow the '&' in the entity reference。为了查看这些结果,我运行了整个 Spring Boot 应用程序。

【问题讨论】:

    标签: java spring spring-mvc spring-boot integration-testing


    【解决方案1】:

    考虑在您的情况下使用 WireMock (http://wiremock.org/)。 WireMock 帮助您在集成(或单元)测试环境中运行 HTTP 服务器并存根其行为。看看下面的例子(JUnit 测试):

    package com.github.wololock;
    
    import com.github.tomakehurst.wiremock.junit.WireMockRule;
    import org.apache.commons.io.IOUtils;
    import org.junit.Before;
    import org.junit.Rule;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.net.URLConnection;
    import java.nio.charset.Charset;
    
    import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
    import static com.github.tomakehurst.wiremock.client.WireMock.get;
    import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
    import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
    import static org.hamcrest.CoreMatchers.equalTo;
    import static org.hamcrest.CoreMatchers.is;
    import static org.hamcrest.MatcherAssert.assertThat;
    
    public final class WireMockHtmlTest {
    
        @Rule
        public WireMockRule wireMockRule = new WireMockRule(options().port(8080));
    
        @Before
        public void setup() throws IOException {
            final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("html/index.html");
            final String html = new String(IOUtils.toByteArray(inputStream), Charset.forName("UTF-8"));
    
            wireMockRule.stubFor(get(urlEqualTo("/index"))
                        .willReturn(aResponse()
                                .withBody(html)
                                .withHeader("Content-Type", "text/html; charset=UTF-8")
                        )
            );
        }
    
        @Test
        public void test() throws IOException, InterruptedException {
            //given:
            final URLConnection connection = new URL("http://localhost:8080/index").openConnection();
            //when:
            final String body = IOUtils.toString(connection.getInputStream(), Charset.forName("UTF-8"));
            //then:
            assertThat(body.contains("Hello world!"), is(equalTo(true)));
        }
    }
    

    此测试加载存储在src/test/resources/html/index.html 中的 HTML 文件的内容,该文件包含:

    <html>
    <head>
        <title>Hello world!</title>
    </head>
    <body>
        <h1>Hello world!</h1>
    </body>
    </html>
    

    如果您想在集成测试中使用 WireMock,只需做几件事:

    1. WireMockRule 指定@Rule(它处理正在运行的HTTP 服务器)。值得一提的是 - 使用未使用的端口号,否则服务器将无法启动。
    2. @Before 阶段的存根服务器行为(您可以在此处找到有关存根的更多信息 - http://wiremock.org/docs/stubbing/
    3. 准备一个连接到正在运行的服务器的测试用例(localhost)。
    4. 您不必担心关闭 HTTP 服务器 - 运行测试完成后它会关闭。

    我特意粘贴了所有导入,以便您查看使用了哪些类。

    希望对你有帮助:)

    【讨论】:

    • 我使用你的建议来模拟对 中的 url 调用的响应。我对您的代码进行了一些编辑以使其正常工作:aResponse().withBody(img).withHeader("Content-Type", "image/jpeg")。在这种情况下,img 参数是一个字节数组。 WireMock 绝对可以在我的项目中使用,ty。如果没有更好的答案,我会将其标记为答案。
    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 2015-07-10
    • 1970-01-01
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2020-03-11
    相关资源
    最近更新 更多