I have the following Spring Boot that I want to test using JUnit 5 test and Mockito:
Service:
public interface FxRatesService {
Optional<FxResponseDto> searchFxRates(String sourceCurrency, String targetCurrency, Instant fxTime);
}
Service implementation:
@Service
public class FxRatesServiceImpl implements FxRatesService {
private static final Logger logger = LoggerFactory.getLogger(FxRatesServiceImpl.class);
private FxRatesRepository fxRatesRepository;
public FxRatesServiceImpl() {
}
@Autowired
public FxRatesServiceImpl(FxRatesRepository fxRatesRepository) {
this.fxRatesRepository = fxRatesRepository;
}
@Override
public Optional<FxResponseDto> searchFxRates(String sourceCurrency, String targetCurrency, Instant fxTime)
{
FxRates sourceCurrencyRate = fxRatesRepository.findByCurrencyAndCreatedAt(sourceCurrency, fxTime);
FxRates targetCurrencyRate = fxRatesRepository.findByCurrencyAndCreatedAt(targetCurrency, fxTime);
double sourceRate = sourceCurrencyRate.getRate();
double targetRate = targetCurrencyRate.getRate();
double bidSourceToTarget = calculateBid(sourceRate, targetRate);
double askTargetToSource = calculateAsk(targetRate, sourceRate);
double midSourceToTarget = calculateMid(bidSourceToTarget, askTargetToSource);
FxResponseDto obj = FxResponseDto.builder()
.bidRate(BigDecimal.valueOf(bidSourceToTarget))
.midRate(BigDecimal.valueOf(midSourceToTarget))
.askRate(BigDecimal.valueOf(askTargetToSource))
.build();
return Optional.of(obj);
}
// Method to calculate the bid rate of Currency A in terms of Currency B
private static double calculateBid(double bidA, double askB)
{
return bidA / askB;
}
// Method to calculate the ask rate of Currency A in terms of Currency B
private static double calculateAsk(double askA, double bidB)
{
return askA / bidB;
}
// Method to calculate the mid-rate given bid and ask rates
private static double calculateMid(double bidRate, double askRate)
{
return (bidRate + askRate) / 2.0;
}
}
Repository:
@Repository
public interface FxRatesRepository extends JpaRepository<FxRates, Long>, JpaSpecificationExecutor<FxRates>, CrudRepository<FxRates, Long> {
FxRates findByCurrencyAndCreatedAt(String currency, Instant fxTime);
}
I created this Junit test:
@SpringBootTest
@ExtendWith(MockitoExtension.class)
public class FxRatesServiceImplTest {
@Mock
private FxRatesRepository fxRatesRepository;
@InjectMocks
private FxRatesService fxRatesService;
@InjectMocks
private FxRatesServiceImpl fxRatesServiceImpl;
private FxRates sourceCurrencyRate;
private FxRates targetCurrencyRate;
private Instant fxTime;
@BeforeEach
void init()
{
fxTime = Instant.now();
sourceCurrencyRate = new FxRates();
sourceCurrencyRate.setCurrency("USD");
sourceCurrencyRate.setCreatedAt(fxTime);
sourceCurrencyRate.setRate(1.2);
targetCurrencyRate = new FxRates();
targetCurrencyRate.setCurrency("EUR");
targetCurrencyRate.setCreatedAt(fxTime);
targetCurrencyRate.setRate(0.9);
}
@Test
public void searchFxRatesTest()
{
when(fxRatesRepository.findByCurrencyAndCreatedAt(eq("USD"), any(Instant.class)))
.thenReturn(sourceCurrencyRate);
when(fxRatesRepository.findByCurrencyAndCreatedAt(eq("EUR"), any(Instant.class)))
.thenReturn(targetCurrencyRate);
Optional<FxResponseDto> response = fxRatesServiceImpl.searchFxRates("USD", "EUR", fxTime);
assertTrue(response.isPresent());
FxResponseDto fxResponseDto = response.get();
FxRatesServiceImpl obj = new FxRatesServiceImpl();
double expectedBidRate = ReflectionTestUtils.invokeMethod(obj, "calculateBid", sourceCurrencyRate.getRate(), targetCurrencyRate.getRate());
double expectedAskRate = ReflectionTestUtils.invokeMethod(obj, "calculateAsk", targetCurrencyRate.getRate(), sourceCurrencyRate.getRate());
double expectedMidRate = ReflectionTestUtils.invokeMethod(obj, "calculateMid", expectedBidRate, expectedAskRate);
assertEquals(BigDecimal.valueOf(expectedBidRate), fxResponseDto.getBidRate());
assertEquals(BigDecimal.valueOf(expectedMidRate), fxResponseDto.getMidRate());
assertEquals(BigDecimal.valueOf(expectedAskRate), fxResponseDto.getAskRate());
}
}
But when I run the JUnit test I get error:
FxRatesServiceImplTest > searchFxRatesTest() FAILED
... org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException at DataSourceProperties.java:186
Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:648
Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:177
Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:648
Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:177
Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException at DataSourceProperties.java:186
Do you know how I can properly mock the datasource so that I mock the request and the result into the Test file?