konta-walutowe/src/test/java/eu/ztsh/wymiana/service/NbpServiceTest.java

117 lines
4.8 KiB
Java

package eu.ztsh.wymiana.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.ztsh.wymiana.EntityCreator;
import eu.ztsh.wymiana.WireMockExtension;
import eu.ztsh.wymiana.exception.NoDataException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.Mockito;
import org.springframework.web.client.RestClient;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ExtendWith(WireMockExtension.class)
class NbpServiceTest {
private static final ZoneId zone = ZoneId.of("Europe/Warsaw");
private static final LocalDate today = LocalDate.of(2024, Month.MAY, 12); // Sunday
private static Clock clock;
private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private final RestClient restClient = RestClient.builder().baseUrl(WireMockExtension.baseUrl).build();
private NbpService nbpService;
@BeforeAll
static void prepare() {
clock = Mockito.mock(Clock.class);
Mockito.when(clock.getZone()).thenReturn(zone);
}
@BeforeEach
void prepareTest() {
nbpService = new NbpService(clock, restClient);
}
@DisplayName("Check if fetch date is calculated properly: weekdays")
@ParameterizedTest
@EnumSource(value = DayOfWeek.class, names = {"SATURDAY", "SUNDAY"}, mode = EnumSource.Mode.EXCLUDE)
void getFetchDateOnWorkingDayTest(DayOfWeek dayOfWeek) {
updateClock(dayOfWeek);
assertThat(nbpService.getFetchDate()).isEqualTo(
switch (dayOfWeek) {
case MONDAY -> LocalDate.of(2024, Month.MAY, 6);
case TUESDAY -> LocalDate.of(2024, Month.MAY, 7);
case WEDNESDAY -> LocalDate.of(2024, Month.MAY, 8);
case THURSDAY -> LocalDate.of(2024, Month.MAY, 9);
case FRIDAY -> LocalDate.of(2024, Month.MAY, 10);
default -> null;
}
);
}
@DisplayName("Check if fetch date is calculated properly: weekends")
@ParameterizedTest
@EnumSource(value = DayOfWeek.class, names = {"SATURDAY", "SUNDAY"})
void getFetchDateOnWeekendTest(DayOfWeek dayOfWeek) {
updateClock(dayOfWeek);
assertThat(nbpService.getFetchDate()).isEqualTo(LocalDate.of(2024, Month.MAY, 10));
}
@DisplayName("Fetch rates straight from server")
@Test
void getWithoutCacheTest() throws JsonProcessingException {
var date = dtf.format(updateClock(DayOfWeek.FRIDAY));
var url = "/api/exchangerates/rates/c/usd/%s/".formatted(date);
WireMockExtension.response(url, 200, new ObjectMapper().writeValueAsString(EntityCreator.rates(date)));
try {
assertThat(nbpService.getSellRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.SELL_RATE);
} finally {
WireMockExtension.verifyGet(1, url);
}
}
@DisplayName("Fetch rates from cache")
@Test
void getWithCacheTest() throws JsonProcessingException {
var date = dtf.format(updateClock(DayOfWeek.FRIDAY));
var url = "/api/exchangerates/rates/c/usd/%s/".formatted(date);
WireMockExtension.response(url, 200, new ObjectMapper().writeValueAsString(EntityCreator.rates(date)));
// save to cache
assertThat(nbpService.getSellRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.SELL_RATE);
// get from cache
assertThat(nbpService.getBuyRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.BUY_RATE);
WireMockExtension.verifyGet(1, url);
}
@DisplayName("Support 404: invalid currency or no data")
@Test
void getInvalidCurrencyTest() {
var date = dtf.format(updateClock(DayOfWeek.FRIDAY));
var url = "/api/exchangerates/rates/c/usb/%s/".formatted(date);
WireMockExtension.response(url, 404, "404 NotFound - Not Found - Brak danych");
assertThatThrownBy(() -> nbpService.getSellRate("usb")).isInstanceOf(NoDataException.class);
WireMockExtension.verifyGet(1, url);
}
private LocalDate updateClock(DayOfWeek dayOfWeek) {
var date = today.with(TemporalAdjusters.previousOrSame(dayOfWeek));
Mockito.when(clock.instant()).thenReturn(date.atStartOfDay(zone).toInstant());
return LocalDate.from(date);
}
}