Introduction to Testing in Java
Maria Milusheva
Senior Software Engineer
Recall the dependency flow in the previous lesson: The currency exchange app depends on the bank server:
Impossible to verify calculations because currency exchange rates are inherently unpredictable.
Mocking - creating simulated objects or behaviors for real objects that are difficult to use in tests, allowing us to test without relying on external dependencies.
Mockito - powerful Java library for creating mocks.
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Consider the previous lesson:
public double convertEuroTo(String currency, double amount) {
double rate = this.bank.getRateEuroTo(currency);
return amount * rate;
}
➡ Make predicable object for EuropeanCentralBankServer
for testing
This is how we test with mocks:
@Test void convert_returnsExpectedValue() { EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class); ExchangeApp exchangeApp = new ExchangeApp(bank);
// Need to program the mock so it works when(bank.getRateEuroTo("USD")).thenReturn(1.1);
// Calls getRateEuroTo from the mock object, obtaining our pre-programmed values double result = exchangeApp.convertEuroTo("USD", 1000); assertEquals(1100, result); // We can now assert on exact return values }
We should never forget to program our mocks:
@Test
void convert_returnsExpectedValue() {
EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// No mock programming - mock bank object doesn't know how to respond to getRateEuroTo
double result = exchangeApp.convertEuroTo("USD", 1000);
assertEquals(1100, result); // Will fail due to lack of mock setup
}
The test fails with:
org.opentest4j.AssertionFailedError:
Expected :1100.0
Actual :0.0
Programming a mock is referred to as stubbing.
Stubbing - providing minimal, pre-defined answers to calls made during the test, usually not responding at all to anything outside what’s programmed for the test.
Mockito can also simulate error scenarios:
EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// Instead of thenReturn() use thenThrow()
when(bank.getRateEuroTo("USD"))
.thenThrow(new RuntimeException("Bank server unavailable."));
exchangeApp.convertEuroTo("USD", 1000); // getRateEuroTo will throw exception
Introduction to Testing in Java