package org.learning.by.example.reactive.microservices.services; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.learning.by.example.reactive.microservices.exceptions.GetSunriseSunsetException; import org.learning.by.example.reactive.microservices.model.GeographicCoordinates; import org.learning.by.example.reactive.microservices.model.SunriseSunset; import org.learning.by.example.reactive.microservices.model.GeoTimesResponse; import org.learning.by.example.reactive.microservices.test.tags.UnitTest; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.mock.mockito.SpyBean; import reactor.core.publisher.Mono; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.core.Is.is; import static org.learning.by.example.reactive.microservices.test.RestServiceHelper.getMonoFromJsonPath; import static org.learning.by.example.reactive.microservices.test.RestServiceHelper.mockWebClient; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @UnitTest @DisplayName("SunriseSunsetServiceImplTests Unit Tests") class SunriseSunsetServiceImplTests { private static final String STATUS_OK = "OK"; private static final String BAD_EXCEPTION = "bad exception"; private static final String SUNRISE_TIME = "2017-05-21T12:53:56+00:00"; private static final String SUNSET_TIME = "2017-05-22T03:16:05+00:00"; private static final double GOOGLE_LAT = 37.4224082; private static final double GOOGLE_LNG = -122.0856086; private static final GeographicCoordinates GOOGLE_LOCATION = new GeographicCoordinates(GOOGLE_LAT, GOOGLE_LNG); private static final Mono<GeographicCoordinates> GOOGLE_LOCATION_MONO = Mono.just(GOOGLE_LOCATION); private static final String GOOGLE_LOCATION_IN_PARAMS = "?lat=" + Double.toString(GOOGLE_LAT) + "&lng=" + Double.toString(GOOGLE_LNG)+"&date=today&formatted=0"; private static final String JSON_OK = "/json/GeoTimesResponse_OK.json"; private static final String JSON_KO = "/json/GeoTimesResponse_KO.json"; private static final String JSON_EMPTY = "/json/GeoTimesResponse_EMPTY.json"; private static final Mono<GeoTimesResponse> SUNRISE_SUNSET_OK = getMonoFromJsonPath(JSON_OK, GeoTimesResponse.class); private static final Mono<GeoTimesResponse> SUNRISE_SUNSET_KO = getMonoFromJsonPath(JSON_KO, GeoTimesResponse.class); private static final Mono<GeoTimesResponse> SUNRISE_SUNSET_EMPTY = getMonoFromJsonPath(JSON_EMPTY, GeoTimesResponse.class); private static final Mono<GeoTimesResponse> LOCATION_EXCEPTION = Mono.error(new GetSunriseSunsetException(BAD_EXCEPTION)); private static final Mono<GeoTimesResponse> BIG_EXCEPTION = Mono.error(new RuntimeException(BAD_EXCEPTION)); @Value("${SunriseSunsetServiceImpl.endPoint}") private String endPoint; @SpyBean(SunriseSunsetService.class) private SunriseSunsetServiceImpl sunriseSunsetService; @Test void getBeamTest() { assertThat(sunriseSunsetService, is(notNullValue())); } @Test void getMockingWebClientTest() { sunriseSunsetService.webClient = mockWebClient(sunriseSunsetService.webClient, SUNRISE_SUNSET_OK); final GeoTimesResponse result = Mono.just(endPoint.concat(GOOGLE_LOCATION_IN_PARAMS)) .transform(sunriseSunsetService::get).block(); assertThat(result, is(notNullValue())); assertThat(result.getStatus(), is(STATUS_OK)); assertThat(result.getResults().getSunrise(), is(SUNRISE_TIME)); assertThat(result.getResults().getSunset(), is(SUNSET_TIME)); reset(sunriseSunsetService.webClient); } @Test void fromLocationTest() { doReturn(SUNRISE_SUNSET_OK).when(sunriseSunsetService).get(any()); final SunriseSunset result = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::fromGeographicCoordinates).block(); assertThat(result, is(notNullValue())); assertThat(result.getSunrise(), is(SUNRISE_TIME)); assertThat(result.getSunset(), is(SUNSET_TIME)); verify(sunriseSunsetService, times(1)).fromGeographicCoordinates(any()); verify(sunriseSunsetService, times(1)).buildUrl(any()); verify(sunriseSunsetService, times(1)).get(any()); verify(sunriseSunsetService, times(1)).createResult(any()); reset(sunriseSunsetService); } @Test void fromLocationKOTest() { doReturn(SUNRISE_SUNSET_KO).when(sunriseSunsetService).get(any()); final SunriseSunset result = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::fromGeographicCoordinates) .onErrorResume(throwable -> { assertThat(throwable, instanceOf(GetSunriseSunsetException.class)); return Mono.empty(); }).block(); assertThat(result, is(nullValue())); verify(sunriseSunsetService, times(1)).fromGeographicCoordinates(any()); verify(sunriseSunsetService, times(1)).buildUrl(any()); verify(sunriseSunsetService, times(1)).get(any()); verify(sunriseSunsetService, times(1)).createResult(any()); reset(sunriseSunsetService); } @Test void fromLocationExceptionTest() { doReturn(LOCATION_EXCEPTION).when(sunriseSunsetService).get(any()); final SunriseSunset result = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::fromGeographicCoordinates) .onErrorResume(throwable -> { assertThat(throwable, instanceOf(GetSunriseSunsetException.class)); return Mono.empty(); }).block(); assertThat(result, is(nullValue())); verify(sunriseSunsetService, times(1)).fromGeographicCoordinates(any()); verify(sunriseSunsetService, times(1)).buildUrl(any()); verify(sunriseSunsetService, times(1)).get(any()); verify(sunriseSunsetService, times(1)).createResult(any()); reset(sunriseSunsetService); } @Test void fromLocationBigExceptionTest() { doReturn(BIG_EXCEPTION).when(sunriseSunsetService).get(any()); final SunriseSunset result = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::fromGeographicCoordinates) .onErrorResume(throwable -> { assertThat(throwable, instanceOf(GetSunriseSunsetException.class)); return Mono.empty(); }).block(); assertThat(result, is(nullValue())); verify(sunriseSunsetService, times(1)).fromGeographicCoordinates(any()); verify(sunriseSunsetService, times(1)).buildUrl(any()); verify(sunriseSunsetService, times(1)).get(any()); verify(sunriseSunsetService, times(1)).createResult(any()); reset(sunriseSunsetService); } @Test void fromLocationErrorTest() { doReturn(SUNRISE_SUNSET_EMPTY).when(sunriseSunsetService).get(any()); final SunriseSunset result = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::fromGeographicCoordinates) .onErrorResume(throwable -> { assertThat(throwable, instanceOf(GetSunriseSunsetException.class)); return Mono.empty(); }).block(); assertThat(result, is(nullValue())); verify(sunriseSunsetService, times(1)).fromGeographicCoordinates(any()); verify(sunriseSunsetService, times(1)).buildUrl(any()); verify(sunriseSunsetService, times(1)).get(any()); verify(sunriseSunsetService, times(1)).createResult(any()); reset(sunriseSunsetService); } @Test void buildUrlTest() { final String url = GOOGLE_LOCATION_MONO.transform(sunriseSunsetService::buildUrl).block(); assertThat(url, is(notNullValue())); assertThat(url, is(endPoint.concat(GOOGLE_LOCATION_IN_PARAMS))); } }