Draft support for WebTestClient (#514)

* Draft support for WebTestClient
* Share some common code between MockMvc and WebTestClient
* Fix co-ordinates of server stubs
* Fix project names in Gradle
This commit is contained in:
Dave Syer
2018-01-12 14:12:31 +00:00
committed by Marcin Grzejszczak
parent 74b843d76b
commit 92848125b9
67 changed files with 3388 additions and 214 deletions

View File

@@ -0,0 +1,13 @@
package com.example.loan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,73 @@
package com.example.loan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.example.loan.model.FraudCheckStatus;
import com.example.loan.model.FraudServiceRequest;
import com.example.loan.model.FraudServiceResponse;
import com.example.loan.model.LoanApplication;
import com.example.loan.model.LoanApplicationResult;
import com.example.loan.model.LoanApplicationStatus;
@Service
@ConfigurationProperties("service")
public class LoanApplicationService {
private static final String FRAUD_SERVICE_JSON_VERSION_1 =
"application/vnd.fraud.v1+json";
private final RestTemplate restTemplate;
private int port = 8080;
public LoanApplicationService() {
this.restTemplate = new RestTemplate();
}
public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
FraudServiceRequest request =
new FraudServiceRequest(loanApplication);
FraudServiceResponse response =
sendRequestToFraudDetectionService(request);
return buildResponseFromFraudResult(response);
}
private FraudServiceResponse sendRequestToFraudDetectionService(
FraudServiceRequest request) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
// tag::client_call_server[]
ResponseEntity<FraudServiceResponse> response =
restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
new HttpEntity<>(request, httpHeaders),
FraudServiceResponse.class);
// end::client_call_server[]
return response.getBody();
}
private LoanApplicationResult buildResponseFromFraudResult(FraudServiceResponse response) {
LoanApplicationStatus applicationStatus = null;
if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
} else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
}
return new LoanApplicationResult(applicationStatus, response.getRejectionReason());
}
public void setPort(int port) {
this.port = port;
}
}

View File

@@ -0,0 +1,21 @@
package com.example.loan.model;
public class Client {
private String pesel;
public Client() {
}
public Client(String pesel) {
this.pesel = pesel;
}
public String getPesel() {
return pesel;
}
public void setPesel(String pesel) {
this.pesel = pesel;
}
}

View File

@@ -0,0 +1,5 @@
package com.example.loan.model;
public enum FraudCheckStatus {
OK, FRAUD
}

View File

@@ -0,0 +1,34 @@
package com.example.loan.model;
import java.math.BigDecimal;
public class FraudServiceRequest {
private String clientId;
private BigDecimal loanAmount;
public FraudServiceRequest() {
}
public FraudServiceRequest(LoanApplication loanApplication) {
this.clientId = loanApplication.getClient().getPesel();
this.loanAmount = loanApplication.getAmount();
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public BigDecimal getLoanAmount() {
return loanAmount;
}
public void setLoanAmount(BigDecimal loanAmount) {
this.loanAmount = loanAmount;
}
}

View File

@@ -0,0 +1,27 @@
package com.example.loan.model;
public class FraudServiceResponse {
private FraudCheckStatus fraudCheckStatus;
private String rejectionReason;
public FraudServiceResponse() {
}
public FraudCheckStatus getFraudCheckStatus() {
return fraudCheckStatus;
}
public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
this.fraudCheckStatus = fraudCheckStatus;
}
public String getRejectionReason() {
return rejectionReason;
}
public void setRejectionReason(String rejectionReason) {
this.rejectionReason = rejectionReason;
}
}

View File

@@ -0,0 +1,44 @@
package com.example.loan.model;
import java.math.BigDecimal;
public class LoanApplication {
private Client client;
private BigDecimal amount;
private String loanApplicationId;
public LoanApplication() {
}
public LoanApplication(Client client, double amount) {
this.client = client;
this.amount = BigDecimal.valueOf(amount);
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getLoanApplicationId() {
return loanApplicationId;
}
public void setLoanApplicationId(String loanApplicationId) {
this.loanApplicationId = loanApplicationId;
}
}

View File

@@ -0,0 +1,32 @@
package com.example.loan.model;
public class LoanApplicationResult {
private LoanApplicationStatus loanApplicationStatus;
private String rejectionReason;
public LoanApplicationResult() {
}
public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus, String rejectionReason) {
this.loanApplicationStatus = loanApplicationStatus;
this.rejectionReason = rejectionReason;
}
public LoanApplicationStatus getLoanApplicationStatus() {
return loanApplicationStatus;
}
public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
this.loanApplicationStatus = loanApplicationStatus;
}
public String getRejectionReason() {
return rejectionReason;
}
public void setRejectionReason(String rejectionReason) {
this.rejectionReason = rejectionReason;
}
}

View File

@@ -0,0 +1,5 @@
package com.example.loan.model;
public enum LoanApplicationStatus {
LOAN_APPLIED, LOAN_APPLICATION_REJECTED
}

View File

@@ -0,0 +1,5 @@
server.port: 8097
logging:
level:
org.springframework.web.client: debug
com.github.tomakehurst.wiremock: trace

View File

@@ -0,0 +1,71 @@
package com.example.loan;
import static org.assertj.core.api.Assertions.assertThat;
import java.nio.charset.Charset;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StreamUtils;
import com.example.loan.model.Client;
import com.example.loan.model.LoanApplication;
import com.example.loan.model.LoanApplicationResult;
import com.example.loan.model.LoanApplicationStatus;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
@RunWith(SpringRunner.class)
@SpringBootTest(properties="service.port=${wiremock.server.port}")
@AutoConfigureWireMock(port=0)
public class LoanApplicationServiceTests {
@Autowired
private LoanApplicationService service;
@Value("classpath:META-INF/com.example/http-server-webclient/0.0.1-SNAPSHOT/mappings/markClientAsFraud.json")
private Resource markClientAsFraud;
@Value("classpath:META-INF/com.example/http-server-webclient/0.0.1-SNAPSHOT/mappings/markClientAsNotFraud.json")
private Resource markClientAsNotFraud;
@Autowired
private WireMockServer server;
@Test
public void shouldSuccessfullyApplyForLoan() throws Exception {
server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
markClientAsNotFraud.getInputStream(), Charset.forName("UTF-8"))));
// given:
LoanApplication application = new LoanApplication(new Client("1234567890"),
123.123);
// when:
LoanApplicationResult loanApplication = service.loanApplication(application);
// then:
assertThat(loanApplication.getLoanApplicationStatus())
.isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
assertThat(loanApplication.getRejectionReason()).isNull();
}
@Test
public void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
server.addStubMapping(StubMapping.buildFrom(StreamUtils.copyToString(
markClientAsFraud.getInputStream(), Charset.forName("UTF-8"))));
// given:
LoanApplication application = new LoanApplication(new Client("1234567890"),
99999);
// when:
LoanApplicationResult loanApplication = service.loanApplication(application);
// then:
assertThat(loanApplication.getLoanApplicationStatus())
.isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
}
}

View File

@@ -0,0 +1,58 @@
package com.example.loan;
import com.example.loan.model.Client;
import com.example.loan.model.LoanApplication;
import com.example.loan.model.LoanApplicationResult;
import com.example.loan.model.LoanApplicationStatus;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureStubRunner(ids = "com.example:http-server-webclient")
public class LoanApplicationServiceusingStubRunnerTests {
@Autowired LoanApplicationService service;
@Value("${stubrunner.runningstubs.http-server-webclient.port}") int port;
@Before
public void setup() {
this.service.setPort(this.port);
}
@Test
public void shouldSuccessfullyApplyForLoan() throws Exception {
// given
LoanApplication application = new LoanApplication(new Client("1234567890"),
123.123);
// when:
LoanApplicationResult loanApplication = service.loanApplication(application);
// then:
assertThat(loanApplication.getLoanApplicationStatus())
.isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
assertThat(loanApplication.getRejectionReason()).isNull();
}
@Test
public void shouldBeRejectedDueToAbnormalLoanAmount() throws Exception {
// given:
LoanApplication application = new LoanApplication(new Client("1234567890"),
99999);
// when:
LoanApplicationResult loanApplication = service.loanApplication(application);
// then:
assertThat(loanApplication.getLoanApplicationStatus())
.isEqualTo(LoanApplicationStatus.LOAN_APPLICATION_REJECTED);
assertThat(loanApplication.getRejectionReason()).isEqualTo("Amount too high");
}
}