如何为基于字符串条件从数组中过滤元素的方法编写测试
How to write a test for a method which is filtering elements from an array based on string criteria
我有一个 Car
class 的类别字段是 String
:
public class Car {
private String category;
public Car(String category) {
this.category = category;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
我有这个方法,它使用 contains()
方法过滤掉基于 String
的数组中的元素,只保留跑车。我知道这是个坏主意,只是想写我的第一个单元测试。你能帮我理解从哪里开始吗?一般来说,测试循环过滤逻辑的最佳实践是什么。
private List<Car> filterOutEverythingExceptSportCars(List<Car> cars) {
List<Car> filteredCarsList = new ArrayList<>();
for (int i = 0; i < cars.size(); i++) {
if (cars.get(i).getCategory().contains("sport")) {
filteredCarsList.add(cars.get(i));
}
}
return filteredCarsList;
}
您可以查看 Stream 并像这样使用过滤器运算符。
private static List<Car> filterOutSportCars(List<Car> cars) {
return cars.stream().filter(car -> !car.category.contains("sport")).collect(Collectors.toList());
}
只需测试合约 - 如果您输入 <something>
,那么您期望返回什么?例如,如果我调用 filterOutEverythingExceptSportsCars(null)
、filterOutEverythingExceptSportsCars(Collections.emptyList())
或 filterOutEverythingExceptSportsCars(Arrays.asList(car1, null, car2))
等
会发生什么
然后围绕这一系列先决条件、操作和预期结果构建测试。所以你的第一个测试可能是:
@Test
givenListOfCarsIsNull_whenFilteringOutEverythingExceptSportsCars_thenReturnEmptyList() {
final List<Car> in = null; //precondition
final List<Car> out = filterOutEverythingExceptSportsCars(in); //calling the method
assertTrue(out.isEmpty()); //verifying expected output
}
如果您希望在这种情况下返回一个空列表。相反,您可能期望抛出异常或其他东西。
首先,您需要使您的方法可测试。在您的实现中,它是一个私有实例方法。由于您没有使用实例中的任何其他内容,因此可以将其设为包私有静态方法:
static List<Car> filterOutEverythingExceptSportCars(List<Car> cars) {
List<Car> filteredCarsList = new ArrayList<>();
for (Car car: cars) {
if (!car.getCategory().contains("sport")) {
filteredCarsList.add(car);
}
}
return filteredCarsList;
}
现在您可以轻松编写带有要比较的输入和输出列表的单元测试:
@Test
public static void testFilterOutEverythingExceptSportCars() {
List<Car> cars = ...;
List<Car> actual = filterOutEverythingExceptSportCars(cars);
List<Car> expected = ...;
assertEquals(expected, actual);
}
您只需要静态导入 filterOutEverythingExceptSportCars
方法并将测试 class 放在与实现相同的包中。
请注意,for-loop 的改进取决于您申请,而不是强制性的。我也没有更改命名或 if-condition 以匹配。只需编写您的测试并迭代您的实现,直到您最喜欢它...
也许你想尝试 kotlin(编译成 java 字节码):
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
class Car(var category: String)
fun sportCars(list: List<Car>) = list.filter { it.category.contains("sport") }
class CarTests {
@Test
fun `one ferrari and one truck`() {
val ferrari = Car("ferrarisportcar")
val truck = Car("truck")
val sportCars = sportCars(listOf(ferrari, truck))
assertThat(sportCars).containsOnly(ferrari)
}
}
您可以混合使用 kotlin 和 java。因此,一个选项可能是使用 java 作为生产代码,使用 kotlin 作为测试代码。
我有一个 Car
class 的类别字段是 String
:
public class Car {
private String category;
public Car(String category) {
this.category = category;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
我有这个方法,它使用 contains()
方法过滤掉基于 String
的数组中的元素,只保留跑车。我知道这是个坏主意,只是想写我的第一个单元测试。你能帮我理解从哪里开始吗?一般来说,测试循环过滤逻辑的最佳实践是什么。
private List<Car> filterOutEverythingExceptSportCars(List<Car> cars) {
List<Car> filteredCarsList = new ArrayList<>();
for (int i = 0; i < cars.size(); i++) {
if (cars.get(i).getCategory().contains("sport")) {
filteredCarsList.add(cars.get(i));
}
}
return filteredCarsList;
}
您可以查看 Stream 并像这样使用过滤器运算符。
private static List<Car> filterOutSportCars(List<Car> cars) {
return cars.stream().filter(car -> !car.category.contains("sport")).collect(Collectors.toList());
}
只需测试合约 - 如果您输入 <something>
,那么您期望返回什么?例如,如果我调用 filterOutEverythingExceptSportsCars(null)
、filterOutEverythingExceptSportsCars(Collections.emptyList())
或 filterOutEverythingExceptSportsCars(Arrays.asList(car1, null, car2))
等
然后围绕这一系列先决条件、操作和预期结果构建测试。所以你的第一个测试可能是:
@Test
givenListOfCarsIsNull_whenFilteringOutEverythingExceptSportsCars_thenReturnEmptyList() {
final List<Car> in = null; //precondition
final List<Car> out = filterOutEverythingExceptSportsCars(in); //calling the method
assertTrue(out.isEmpty()); //verifying expected output
}
如果您希望在这种情况下返回一个空列表。相反,您可能期望抛出异常或其他东西。
首先,您需要使您的方法可测试。在您的实现中,它是一个私有实例方法。由于您没有使用实例中的任何其他内容,因此可以将其设为包私有静态方法:
static List<Car> filterOutEverythingExceptSportCars(List<Car> cars) {
List<Car> filteredCarsList = new ArrayList<>();
for (Car car: cars) {
if (!car.getCategory().contains("sport")) {
filteredCarsList.add(car);
}
}
return filteredCarsList;
}
现在您可以轻松编写带有要比较的输入和输出列表的单元测试:
@Test
public static void testFilterOutEverythingExceptSportCars() {
List<Car> cars = ...;
List<Car> actual = filterOutEverythingExceptSportCars(cars);
List<Car> expected = ...;
assertEquals(expected, actual);
}
您只需要静态导入 filterOutEverythingExceptSportCars
方法并将测试 class 放在与实现相同的包中。
请注意,for-loop 的改进取决于您申请,而不是强制性的。我也没有更改命名或 if-condition 以匹配。只需编写您的测试并迭代您的实现,直到您最喜欢它...
也许你想尝试 kotlin(编译成 java 字节码):
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
class Car(var category: String)
fun sportCars(list: List<Car>) = list.filter { it.category.contains("sport") }
class CarTests {
@Test
fun `one ferrari and one truck`() {
val ferrari = Car("ferrarisportcar")
val truck = Car("truck")
val sportCars = sportCars(listOf(ferrari, truck))
assertThat(sportCars).containsOnly(ferrari)
}
}
您可以混合使用 kotlin 和 java。因此,一个选项可能是使用 java 作为生产代码,使用 kotlin 作为测试代码。