PaymentGatewayControllerTest.java
Bridget/payment-gateway-challenge-java/src/test/java/com/checkout/payment/gateway/controller/PaymentGatewayControllerTest.java
package com.checkout.payment.gateway.controller;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.checkout.payment.gateway.enums.PaymentStatus;
import com.checkout.payment.gateway.model.BankPaymentResponse;
import com.checkout.payment.gateway.model.PostPaymentResponse;
import com.checkout.payment.gateway.repository.PaymentsRepository;
import java.time.LocalDate;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
@AutoConfigureMockMvc
class PaymentGatewayControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
PaymentsRepository paymentsRepository;
@MockBean
private RestTemplate restTemplate;
private static final String PROCESS_PAYMENT_ENDPOINT = "/api/payments";
@Test
void shouldReturnCorrectPaymentWhenPaymentWithIdExist() throws Exception {
PostPaymentResponse payment = PostPaymentResponse.builder()
.cardNumberLastFour("4321")
.id(UUID.randomUUID())
.amount(10)
.currency("USD")
.status(PaymentStatus.AUTHORIZED)
.expiryYear(2024)
.expiryMonth(12)
.build();
paymentsRepository.add(payment);
mvc.perform(MockMvcRequestBuilders.get(PROCESS_PAYMENT_ENDPOINT + "/" + payment.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(payment.getStatus().getName()))
.andExpect(jsonPath("$.card_number_last_four").value(payment.getCardNumberLastFour()))
.andExpect(jsonPath("$.expiry_month").value(payment.getExpiryMonth()))
.andExpect(jsonPath("$.expiry_year").value(payment.getExpiryYear()))
.andExpect(jsonPath("$.currency").value(payment.getCurrency()))
.andExpect(jsonPath("$.amount").value(payment.getAmount()));
}
@Test
void shouldReturnNotFoundWhenPaymentWithIdDoesNotExist() throws Exception {
mvc.perform(MockMvcRequestBuilders.get(PROCESS_PAYMENT_ENDPOINT + "/" + UUID.randomUUID()))
.andExpect(status().isNotFound())
.andExpect(jsonPath("$.error").value("Payment not found"));
}
@Test
void shouldCreatePaymentWhenRequestIsValid() throws Exception {
when(restTemplate.postForObject(anyString(), any(), eq(BankPaymentResponse.class)))
.thenReturn(
BankPaymentResponse.builder()
.authorized(true)
.authorizationCode("00000000-0000-0000-0000-000000000001")
.build());
LocalDate nextMonth = LocalDate.now().plusMonths(1);
int year = nextMonth.getYear();
int month = nextMonth.getMonthValue();
String validRequest = """
{
"card_number": "2222405343248877",
"expiry_month": %d,
"expiry_year": %d,
"currency": "GBP",
"amount": 100,
"cvv": "123"
}
""".formatted(month, year);
mvc.perform(MockMvcRequestBuilders.post(PROCESS_PAYMENT_ENDPOINT)
.contentType(MediaType.APPLICATION_JSON)
.content(validRequest))
.andExpect(status().isCreated());
}
@Test
void shouldRejectedWhenRequestDataIsInvalid() throws Exception {
// Expiry date is in the past -> invalid
int lastYear = LocalDate.now().getYear() - 1;
String invalidRequest = """
{
"card_number": "2222405343248877",
"expiry_month": 1,
"expiry_year": %d,
"currency": "GBP",
"amount": 100,
"cvv": "123"
}
""".formatted(lastYear);
mvc.perform(MockMvcRequestBuilders.post(PROCESS_PAYMENT_ENDPOINT)
.contentType(MediaType.APPLICATION_JSON)
.content(invalidRequest))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.error").value(PaymentStatus.REJECTED.getName()));
}
@Test
void shouldRejectedWhenRequestFieldIsMissing() throws Exception {
int thisYear = LocalDate.now().getYear();
// Missing "currency"
String invalidRequest = """
{
"card_number": "2222405343248877",
"expiry_month": 1,
"expiry_year": %d,
"amount": 100,
"cvv": "123"
}
""".formatted(thisYear);
mvc.perform(MockMvcRequestBuilders.post(PROCESS_PAYMENT_ENDPOINT)
.contentType(MediaType.APPLICATION_JSON)
.content(invalidRequest))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.error").value(PaymentStatus.REJECTED.getName()));
}
}
関連記事
PaymentGatewayApplication.java
PaymentGatewayApplication.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/PaymentGatewayApplication.java).
記事を読む →ApplicationConfiguration.java
ApplicationConfiguration.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/configuration/ApplicationConfiguration.java).
記事を読む →RequestResponseLogger.java
RequestResponseLogger.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/configuration/RequestResponseLogger.java).
記事を読む →PaymentGatewayController.java
PaymentGatewayController.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/controller/PaymentGatewayController.java).
記事を読む →PaymentStatus.java
PaymentStatus.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/enums/PaymentStatus.java).
記事を読む →BankErrorException.java
BankErrorException.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/exception/BankErrorException.java).
記事を読む →