Current post type: post
WeatherService
that fetches weather data from an external WeatherAPI
. We’ll use a stub to simulate the behavior of the WeatherAPI
to focus on testing the WeatherService
.The WeatherService
class depends on the WeatherAPI
to fetch weather information. We want to test the WeatherService
without calling the actual external API.
// Weather API Interface (Dependency)
public interface WeatherAPI {
String getWeather(String city);
}
// Weather Service (Under Test)
public class WeatherService {
private final WeatherAPI weatherAPI;
public WeatherService(WeatherAPI weatherAPI) {
this.weatherAPI = weatherAPI;
}
public String getWeatherInfo(String city) {
String weather = weatherAPI.getWeather(city);
if ("Sunny".equals(weather)) {
return "It's a sunny day!";
} else if ("Rainy".equals(weather)) {
return "It's a rainy day!";
} else {
return "Weather information unavailable";
}
}
}
WeatherAPI
:We create a simple stub for WeatherAPI
that returns hardcoded weather data.
// Stub Implementation for WeatherAPI
public class WeatherAPIStub implements WeatherAPI {
@Override
public String getWeather(String city) {
if ("New York".equals(city)) {
return "Sunny";
} else if ("Seattle".equals(city)) {
return "Rainy";
}
return "Unknown"; // Default case for other cities
}
}
Now, let’s write unit tests for WeatherService
using the WeatherAPIStub
to simulate the weather API’s behavior.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class WeatherServiceTest {
@Test
public void testGetWeatherInfoSunny() {
// Arrange: Use the stub
WeatherAPI weatherAPIStub = new WeatherAPIStub();
WeatherService weatherService = new WeatherService(weatherAPIStub);
// Act: Call the method with "New York" which returns "Sunny" from the stub
String weatherInfo = weatherService.getWeatherInfo("New York");
// Assert: Verify the result
assertEquals("It's a sunny day!", weatherInfo);
}
@Test
public void testGetWeatherInfoRainy() {
// Arrange: Use the stub
WeatherAPI weatherAPIStub = new WeatherAPIStub();
WeatherService weatherService = new WeatherService(weatherAPIStub);
// Act: Call the method with "Seattle" which returns "Rainy" from the stub
String weatherInfo = weatherService.getWeatherInfo("Seattle");
// Assert: Verify the result
assertEquals("It's a rainy day!", weatherInfo);
}
@Test
public void testGetWeatherInfoUnknownCity() {
// Arrange: Use the stub
WeatherAPI weatherAPIStub = new WeatherAPIStub();
WeatherService weatherService = new WeatherService(weatherAPIStub);
// Act: Call the method with a city that isn't "New York" or "Seattle"
String weatherInfo = weatherService.getWeatherInfo("Los Angeles");
// Assert: Verify the result for the unknown city
assertEquals("Weather information unavailable", weatherInfo);
}
}
WeatherAPIStub
):
"Sunny"
for “New York” and "Rainy"
for “Seattle”)."Unknown"
.WeatherService
correctly interprets the result from the WeatherAPIStub
.WeatherService
without being dependent on the actual WeatherAPI
.This is another classic example of stubbing external dependencies to isolate the unit under test. Would you like to see another example in a different context?
By MOUSTAFA ALSAYEH© 2025 My Company