【问题标题】:How to mock a service calling another service using resttemplate in spring-boot?如何在spring-boot中使用resttemplate模拟调用另一个服务的服务?
【发布时间】:2019-12-26 07:18:51
【问题描述】:

各位专家下午好,

我有一个要求,我将调用 3 个 REST API 作为单个客户端调用 GET /offers 的一部分,以检索百货商店不同过道中每种产品的可用报价,如下所示

  1. 获取百货商店的所有过道/aisels
  2. 获取通道中的所有产品 /aisles/{aisleID}/products
  3. 获取产品 /product/{productId/offers 的所有报价

    要从我的@Service 类中使用 RestTemplate 交换方法执行此操作:

    ResponseEntity aisles=restTemplate.exchange(url, HttpMethod.GET, requestEntity, Aisles.class);

然后在循环中检索每个 aisleId 并调用第二个 API 以获取产品

ResponseEntity<Products> products= restTemplate.exchange(url,
                    HttpMethod.GET, requestEntity, Products.class);

然后在循环中检索每个productId 并调用第三个 API 以获取优惠

最后整理所有响应,将报价列表发送给客户。

现在,我对编写 JUnit 的 mockito 框架很陌生。我的服务类有一个名为 retrieveAllOffers() 的方法,其中我有上面的 3 个交换方法。

我想知道如何在我的 Junit 中模拟这 3 个调用以获得成功的响应场景。

非常感谢您的帮助。

【问题讨论】:

  • 在这里查看我的answer 以获取有关如何模拟restTemplate#exchange 方法的示例。如果您需要更具体的内容,请在您的问题中添加一些正在测试的类/方法的代码示例。

标签: junit mockito spring-boot-test


【解决方案1】:

您可以仅模拟服务的响应,而不是模拟其余模板。为此,您可以使用 Wiremock (http://wiremock.org/),它提供了一个 api 来存根对特定 URL 的调用,并模拟它们对您喜欢的任何内容的响应并验证它们是否被调用。

对于您的情况,您需要 3 个存根,每个交换一个。例如对于这种方法 restTemplate.exchange(url, GET, requestEntity, Products.class); 你提供的存根看起来像

stubFor(get(urlEqualTo("yourUrl"))
  .willReturn(aResponse()
    .withStatus(200)
    .withBody(new ObjectMapper().writeValueAsString(yourResponseObject)
    .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE))

请注意,您的 url 需要将其服务器指向运行 wiremock 的服务器(如果您使用 java 依赖项和 junit 规则,它将是 localhost:wiremockPort)

设置非常简单,因为您需要在测试中添加一条规则

@Rule public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort()); 看看这里http://wiremock.org/docs/configuration/规则的配置

最后你验证你的存根是用

调用的
verify(getRequestedFor(urlEqualTo("/yourUrl"))
  .withRequestBody(equalTo(new ObjectMapper().writeValueAsString(theObjectThatShouldBePosted))));

希望有所帮助!

【讨论】:

  • 问候迈克尔,非常感谢您的回答。我尝试实现这一点并从 src/test/resources 文件夹下的 application-test.properties 文件中读取 URL,但由于某种原因没有读取该值,我尝试了以下选项 stackoverflow.com/questions/29669393/… 但仍然没有帮助。知道为什么我的属性文件没有被加载吗?谢谢。
  • 您正在尝试从测试中的属性中获取服务位置,对吗?您可能会尝试加载测试类!当您使用 spring boot 运行测试时,spring 将在测试资源文件的根目录中查找 application-test.(properties|yaml) 并加载它。现在,您应该获取主代码的配置文件,而不是在测试中获取 url。这意味着您的主代码中的服务/服务在外部查找此配置并使用属性类加载它。这意味着您也可以在测试中注入该类!
  • 您好,迈克尔,很抱歉延迟回复。这是实现类初始化的问题,因为没有读取属性。我现在使用 @Autowired 注释来自动初始化它,所以它工作得很好。再次感谢您的及时帮助。我已经接受了答案。
  • 别担心!如果您需要任何东西,如果可以的话,我很乐意为您提供帮助。 (也只是提到它。接受答案需要按下标志下的检查,这样人们就会看到这个是解决方案看看这个:stackoverflow.com/help/someone-answers
  • 问候迈克尔,对不起,我是新手。刚刚检查过了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 2016-11-22
相关资源
最近更新 更多