Java 为单元测试创建模拟-改装
有一款命令行应用程序可以使用公共API显示明天的天气预报 示例输出可以如下所示:Java 为单元测试创建模拟-改装,java,api,mocking,retrofit,Java,Api,Mocking,Retrofit,有一款命令行应用程序可以使用公共API显示明天的天气预报 示例输出可以如下所示: Tomorrow (2019/05/01) in city XYZ: Clear Temp: 26.5 °C Wind: 7.6 mph Humidity: 61% 问题:您将如何创建一个测试用例,使测试在没有互联网的情况下不会接触到真正的服务和工作 我试着为它创建junit测试,直到我直接使用api为止,它工作得很好 有人可以帮助我如何为我的单元测试创建一个模拟 App.java import api.Fore
Tomorrow (2019/05/01) in city XYZ:
Clear
Temp: 26.5 °C
Wind: 7.6 mph
Humidity: 61%
问题:您将如何创建一个测试用例,使测试在没有互联网的情况下不会接触到真正的服务和工作
我试着为它创建junit测试,直到我直接使用api为止,它工作得很好
有人可以帮助我如何为我的单元测试创建一个模拟
App.java
import api.ForecastServiceImpl;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.IOException;
import java.time.LocalDate;
public class App {
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Pass city name as an argument");
System.exit(1);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.metaweather.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
LocalDate tomorrow = LocalDate.now().plusDays(1);
ForecastServiceImpl service = new ForecastServiceImpl(retrofit);
System.out.println(service.getForecast(args[0], tomorrow));
}
}
Forecast.java
package model;
import com.google.gson.annotations.SerializedName;
public class Forecast {
private Long id;
@SerializedName("weather_state_name")
private String weatherState;
@SerializedName("wind_speed")
private Double windSpeed;
@SerializedName("the_temp")
private Double temperature;
private Integer humidity;
public Long getId() {
return id;
}
public Forecast setId(Long id) {
this.id = id;
return this;
}
public String getWeatherState() {
return weatherState;
}
public Forecast setWeatherState(String weatherState) {
this.weatherState = weatherState;
return this;
}
public Double getWindSpeed() {
return windSpeed;
}
public Forecast setWindSpeed(Double windSpeed) {
this.windSpeed = windSpeed;
return this;
}
public Double getTemperature() {
return temperature;
}
public Forecast setTemperature(Double temperature) {
this.temperature = temperature;
return this;
}
public Integer getHumidity() {
return humidity;
}
public Forecast setHumidity(Integer humidity) {
this.humidity = humidity;
return this;
}
@Override
public String toString() {
return String.format("%s\nTemp: %.1f °C\nWind: %.1f mph\nHumidity: %d%%",
weatherState, temperature, windSpeed, humidity);
}
}
PathDate.java
package util;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class PathDate {
private final LocalDate date;
public PathDate(LocalDate date) {
this.date = date;
}
@Override public String toString() {
return date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
}
}
Utils.java
package util;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Utils {
public static byte[] readResourceFileToBytes(String filename) {
byte[] fileBytes = new byte[0];
try {
Path path = Paths.get(Utils.class.getClassLoader().getResource(filename).toURI());
fileBytes = Files.readAllBytes(path);
} catch (URISyntaxException|IOException|NullPointerException e) {
e.printStackTrace();
}
return fileBytes;
}
}
service.getForecast(city.getWoeid(),pathDate)
返回给我们一个调用
对象。当我们在这个对象上调用execute
时,就会进行实际的API调用。因为我们不想执行实际的API调用,所以可以尝试模拟调用
对象
我们可以模拟调用
类
Call<List<Forecast>> mockedListForeCast = mock(Call.class);
上面的一行表示,当对模拟对象调用execute函数时,返回一个空的forecast列表
// here I am returning the singleton list, you can return a list of forecast
when(mockedListForeCast.execute()).thenReturn(Response.success(Collections.singletonList()));
这样我们就模拟了API响应,而不必进行实际的API调用
编辑:
您还可以使用
服务.getForecast(city.getWoeid(),pathDate)模拟改造API
返回给我们一个调用
对象。当我们在这个对象上调用execute
时,就会进行实际的API调用。因为我们不想执行实际的API调用,所以可以尝试模拟调用
对象
我们可以模拟调用
类
Call<List<Forecast>> mockedListForeCast = mock(Call.class);
上面的一行表示,当对模拟对象调用execute函数时,返回一个空的forecast列表
// here I am returning the singleton list, you can return a list of forecast
when(mockedListForeCast.execute()).thenReturn(Response.success(Collections.singletonList()));
这样我们就模拟了API响应,而不必进行实际的API调用
编辑:
您还可以使用模拟改装API。您想为
getForecast
函数编写测试,对吗?是,对吗getForecast@DeepakPatankar你能帮我做一个示例测试用例吗?你想为getForecast
函数编写测试吗?是正确的getForecast@DeepakPatankar你能帮我吗帮我看一个测试用例示例?嘿@user1873274,这就是我在代码中编写单元测试的方式。你能检查一下这是否也适用于你吗?您可能需要更改上述答案中的某些行以适应您的情况。谢谢@Deepak,但有一个问题,请解释一下,因为我是新来的。我是否应该创建一个方法mock,在其中我应该使用call类进行模拟,然后定义模拟输出?当然,将添加explanationHey@user1873274,我已经更新了我的答案。请让我知道它是否有帮助。我理解这个概念,它很有帮助。我需要在测试类本身中创建mock方法吗?还是应该单独上课?抱歉问了太多基本的问题。嘿@user1873274,这就是我在代码中编写单元测试的方式。你能检查一下这是否也适用于你吗?您可能需要更改上述答案中的某些行以适应您的情况。谢谢@Deepak,但有一个问题,请解释一下,因为我是新来的。我是否应该创建一个方法mock,在其中我应该使用call类进行模拟,然后定义模拟输出?当然,将添加explanationHey@user1873274,我已经更新了我的答案。请让我知道它是否有帮助。我理解这个概念,它很有帮助。我需要在测试类本身中创建mock方法吗?还是应该单独上课?抱歉问了太基本的问题。
// here I am returning the singleton list, you can return a list of forecast
when(mockedListForeCast.execute()).thenReturn(Response.success(Collections.singletonList()));