如何在spring-boot中编写集成测试时模拟外部rest服务



我有一个控制器,从中调用网关(Spring集成(。在gateway内部,我有几个流,我正在进行一些outboundgateway调用。我把我的集成测试写如下-

@Tag("integrationtest")
@ExtendWith(SpringExtension.class)
@SpringBootTest(
classes = MyWebApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTest {
@LocalServerPort private int port;
TestRestTemplate testRestTemplate = new TestRestTemplate();
HttpHeaders headers = new HttpHeaders();
@Test
void testEntireApplication() {
HttpEntity<LoanProvisionRequest> entity =
new HttpEntity(TestHelper.generateValidLionRequest(), headers);
ResponseEntity<LoanProvisionResponse> response =
testRestTemplate.exchange(
createURLWithPort("/provision"), HttpMethod.POST, entity, LionResponse.class);
assertEquals(1, response.getBody().getASMCreditScoreResultCd());
}
private String createURLWithPort(String uri) {
return "http://localhost:" + port + "/lion-service/v1/decisions" + uri;
}
}

它运行应用程序,从控制器到网关,并按预期运行流。但对于outboundgateway调用,它失败了,因为它说"由于:org.springframework.web.client.ResourceAccessException:POST请求上的I/O错误";http://someurl"因为它无法访问outboundgateway中使用的url。我想以某种方式截取/模拟那些url。我该怎么做?

我试着在同一个班里做下面的事情来模拟url-

MockRestServiceServer mockServer;
@BeforeEach
void setUp() throws JsonProcessingException {
RestTemplate restTemplate = new RestTemplate();
mockServer = MockRestServiceServer.bindTo(restTemplate).build();
DecisionResponse decisionResponse = new DecisionResponse();
creditDecisionResponse.setId("0013478");
creditDecisionResponse.setResponse(null);
creditDecisionResponse.setDescription("dummy Response");
mockServer
.expect(
requestTo(
"http://xyz-some-url:8080/some-other-service/v1/do-decisions/decision"))
.andExpect(method(HttpMethod.POST))
.andRespond(
withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(new ObjectMapper().writeValueAsString(decisionResponse )));
mockServer.verify();
}

但仍然显示了相同的错误,而且当它在网关流中调用outboundgateway时,不知何故它没有被调用。

下面是控制器代码-

public ResponseEntity<LionResponse> getLionsNames(
@RequestBody final @Valid LionRequest req,
BindingResult bindingResult,
@RequestHeader HttpHeaders httpHeaders)
throws JsonProcessingException {
Long dbId = new SequenceGenerator().nextId();
lionsGateway.processLionRequest(
MessageBuilder.withPayload(req).build(),
dbId,
SourceSystem.ONE.getSourceSystemCode()));

下面是网关-

@MessagingGateway
public interface LoansGateway {
@Gateway(requestChannel = "flow.input")
List<Object> processLoanRequest(
@Payload Message lionRequest,
@Header("dbID") Long dbID,
@Header("sourceSystemCode") String sourceSystemCode);
}

下面是SpringIntegrationConfiguration类-

@Bean
public IntegrationFlow flow() {
return flow ->
flow.handle(validatorService, "validateRequest")
.split()
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.scatterGather(
scatterer ->
scatterer
.applySequence(true)
.recipientFlow(savingLionRequestToTheDB())
.recipientFlow(callingANativeMethod())
.recipientFlow(callingAExternalService()),
gatherer -> gatherer.outputProcessor(prepareCDRequest()))
.gateway(getDecision(), f -> f.errorChannel("lionDecisionErrorChannel"))
.to(getDataResp());
}
public IntegrationFlow callingAExternalService() {
return flow ->
flow.handle(
Http.outboundGateway(externalServiceURL)
.httpMethod(HttpMethod.POST)
.expectedResponseType(String.class))
.logAndReply("Cd response");
}

和我使用outboundgateway的其他流一样,但我并没有在任何地方连接Restemplate实例。

因此,您可以在模拟服务器设置中执行以下操作:

RestTemplate restTemplate = new RestTemplate();
mockServer = MockRestServiceServer.bindTo(restTemplate).build();

就是这样。被嘲笑的RestTemplate实例在任何地方都没有使用。

HttpRequestExecutingMessageHandler具有基于RestTemplate:的配置

/**
* Create a handler that will send requests to the provided URI using a provided RestTemplate.
* @param uri The URI.
* @param restTemplate The rest template.
*/
public HttpRequestExecutingMessageHandler(String uri, RestTemplate restTemplate) {

因此,您只需要准确地插入为HTTP出站网关提供的RestTemplate

现在你的嘲讽代码是死胡同。

最新更新