当前位置: 首页 > 知识库问答 >
问题:

测试期间模拟外部服务器

闻人越
2023-03-14

假设应用程序依赖于外部服务器上的REST服务,http://otherserver.com.为了测试,我想在JUnit环境中模拟外部rest调用(通过Wiremck)。启动单独的服务器会消耗时间,而且不容易。使用Wiremck规则看起来是正确的方向。创建模拟控制器并不是一种优雅的方式,因为Wiremck是可用的。

例如get(" http://other server . com/service 3/");

PS:我当然知道我可以通过Mockito模拟一个REST调用。

用Wiremock模拟本地主机很容易。如何使用该代码模拟其他服务器和服务?我从流行的Baeldung例子中复制了部分内容。

public class WireMockDemo {
    @Rule
    public WireMockRule wireMockRule = new WireMockRule();


    @Test
    public void wireMockTestJunitOtherServer() {
        try {
            // **this does not work...** 
            configureFor("otherserver.com", 8080);

            stubFor(get(urlPathMatching("/service2/.*"))
                    .willReturn(aResponse()
                            .withStatus(200)
                            .withHeader("Content-Type", "application/json")
                            .withBody("\"testing-library\": \"WireMock\"")));

            // Test via simple client
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpGet request = new HttpGet("http://otherserver:8080/service2/test");
            HttpResponse httpResponse = httpClient.execute(request);
            String stringResponse = convertHttpResponseToString(httpResponse);
            System.out.println( "Response = " + stringResponse);

            // Test via JUnit
            verify(getRequestedFor(urlEqualTo("/service2/wiremock")));
            assertEquals(200, httpResponse.getStatusLine().getStatusCode());
            assertEquals("application/json", httpResponse.getFirstHeader("Content-Type").getValue());
            assertEquals("\"testing-library\": \"WireMock\"", stringResponse);
        } catch( Exception e) {
            e.printStackTrace();
        }
    }

    // Support methods
    private String convertHttpResponseToString(HttpResponse httpResponse) throws IOException {
        InputStream inputStream = httpResponse.getEntity().getContent();
        return convertInputStreamToString(inputStream);
    }
    private String convertInputStreamToString(InputStream inputStream) {
        Scanner scanner = new Scanner(inputStream, "UTF-8");
        String string = scanner.useDelimiter("\\Z").next();
        scanner.close();
        return string;
    }
}

共有2个答案

敖涵容
2023-03-14
匿名用户

TL;博士:

不,你不能。

WireMock所做的是建立一个Jetty服务器,模拟你需要向其发送请求的远程服务器。但是,它不会更改您的主机文件或 DNS 映射,并自动将您对远程服务器的实际请求“重定向”到本地主机。在测试中,您仍然需要向本地主机发送请求。

如果您使用的是Spring Boot,您可以做的是创建两个<code>应用程序。yml文件(或另一个属性文件)位于maintest包中,密钥结构相同,但值位于src/main/resources/application中。yml是您请求的真实URL(如http://example.com/api),以及src/test/resources/application。yml您将localhost/api放入。

顺便澄清一下,MockMvc不是用于模拟应用程序依赖的外部第三方服务器请求,而是发送到应用程序endpoint的请求。在MockMvc测试中,您的应用程序接收请求,但在WireMock测试中,应用程序发送请求。

一些工作示例:

// configure static, class-level rule for all tests, like @BeforeClass.
// this launches a Jetty server with configurations
@ClassRule
public static WireMockClassRule classRule = new WireMockClassRule(options().
        port(80).httpsPort(443));

// Divide @ClassRule and @Rule,
// to bypass JUnit limitation of "@Rule cannot be static"
@Rule
public WireMockClassRule rule = classRule;


@Test
public void shouldReturnGivenJson() throws Exception {
    // stubFor() also works; givenThat() is more TDD-ish
    givenThat(post(urlEqualTo("/service2/test")) // <----- note here: without host name
            .willReturn(WireMock.aResponse()
                    .withStatus(HttpStatus.OK.value())
                    .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
                    .withBody("{\"status\":\"up\"}")));
    // .... your connection here

我建议从urlEqualTo()开始,不要弄乱正则表达式。然后你进入urlMatching()。

另外,使用org.apache.http.util。EntityUtils从响应中获取内容。这是处理响应的官方内置方式。并且,使用ResponseHandler,因为它将consumer()响应,而无需手动清理资源。

查看Http客户留档了解更多详情。

颜君浩
2023-03-14

您的应用程序代码不应该有http://otherserver.com硬编码,它应该是可配置的。正常运行时,它应该指向http://otherserver.com,在测试模式下运行时,它应该指向http://localhost:

 类似资料:
  • 问题内容: 我有一个ParseService,我想对其进行模拟以测试使用它的所有控制器,我一直在阅读有关茉莉花间谍的信息,但对我来说仍然不清楚。谁能给我一个关于如何模拟定制服务并在Controller测试中使用它的示例吗? 现在,我有一个使用服务插入书的控制器: 服务是这样的: 到目前为止,我的测试如下所示: 现在测试失败: 我做错了什么? 问题答案: 我做错的是没有在beforeEach中将模拟

  • 我想对一个组件的功能进行单元测试。因此,我需要一个模拟服务(根据角度测试指南)。 这里是我的测试床: 那么,嘲笑服务价值的正确方法是什么呢? 弗兰克

  • 我正在用两个应用程序做project:android应用程序(客户端)和rest服务(服务器)。我的android应用程序消耗了我的rest服务。 这两个应用程序都是单独测试的,以确保它们按照预期完成业务。在服务器测试期间,我准备请求并检查服务器响应。在客户机测试期间,我设置了一个简单的http模拟服务器,并针对不同的模拟响应测试客户机的请求。 现在,这个技术很管用。它给了我一种我喜欢的灵活性。我

  • 我有一个关于在junits中使用EasyMock的问题。我们已经为junits配置了一个框架,它使用inmemory derby数据库和EasyMock来测试我们的服务项目。我们将内存中的derby完全用于dao层。问题出现在天气上,是完全使用EasyMock还是在服务层中同时使用EasyMock和derby。以下是场景: 被测试的类在用户服务项目中,IUserService接口也是如此。IAdd

  • 我正在尝试为我的Spring Boot应用程序创建集成测试。其想法是启动一个嵌入式postgres db,并使用TestRestTemplate对我的控制器运行http调用。 问题是我的项目有一个我们用于redis队列的依赖项。 我曾尝试模拟依赖项,其中大多数都能正常工作,但我猜这一次它会抱怨,因为它是而不是: 依赖配置类: 我的测试配置类 我已经在我的config类中尝试了,但是原始的在启动之前