使用@MethodSource 处理异常
Handling exceptions with @MethodSource
我刚开始在 LeetCode 上做一个名为“Two Sum”的练习,但遇到了测试问题。
现在,练习的代码如下所示:
public class TwoSumCalculator {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[j] == target - numbers[i]) {
return new int[]{i, j};
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
}
我的测试是这样的:
class TwoSumCalculatorTest {
TwoSumCalculator twoSumCalculator = new TwoSumCalculator();
@ParameterizedTest
@MethodSource("parameters")
void findIndices(int[] expectedNumbers, int[] inputNumbers, int target) {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
private static Stream<Arguments> parameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6),
Arguments.of(new IllegalArgumentException("No two sum solution"), new int[]{3, 1, 2}, 6));
}
}
虽然前 3 个测试通过了,但我在第 4 个参数中收到以下错误消息:
org.junit.jupiter.api.extension.ParameterResolutionException:在索引 0 处转换参数时出错:没有将类型 java.lang.IllegalArgumentException 的对象转换为类型 [I
的隐式转换
什么是更好的测试方法?
你可以做这样的事情,或者可能只是对抛出异常的情况进行单独的测试。
@ParameterizedTest
@MethodSource("parameters")
void findIndices(int[] expectedNumbers, int[] inputNumbers, int target, Class expectedException) {
if (expectedException != null) {
assertThrows(expectedException, () -> twoSumCalculator.twoSum(inputNumbers, target));
} else {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
}
private static Stream<Arguments> parameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6, null),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9, null),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6, null),
Arguments.of(null, new int[]{3, 1, 2}, 6, IllegalArgumentException.class));
}
与其尝试在同一测试中对成功和失败案例进行参数化,我建议您分别进行测试。这使您可以使用 assertThrows
方法断言抛出的异常,并避免在测试代码中引入逻辑。
类似于:
class TwoSumCalculatorTest {
TwoSumCalculator twoSumCalculator = new TwoSumCalculator();
@ParameterizedTest
@MethodSource("twoSumParameters")
void twoSumSolutions(int[] expectedNumbers, int[] inputNumbers, int target) {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
@ParameterizedTest
@MethodSource("noTwoSumParameters")
void noTwoSumSolutions(int[] inputNumbers, int target) {
assertThrows(IllegalArgumentException.class, () -> {
twoSumCalculator.twoSum(inputNumbers, target);
})
}
private static Stream<Arguments> twoSumParameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6)
);
private static Stream<Arguments> noTwoSumParameters() {
return Stream.of(
Arguments.of(new int[]{3, 1, 2}, 6)
// Could add more exceptional cases here
);
}
我刚开始在 LeetCode 上做一个名为“Two Sum”的练习,但遇到了测试问题。
现在,练习的代码如下所示:
public class TwoSumCalculator {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[j] == target - numbers[i]) {
return new int[]{i, j};
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
}
我的测试是这样的:
class TwoSumCalculatorTest {
TwoSumCalculator twoSumCalculator = new TwoSumCalculator();
@ParameterizedTest
@MethodSource("parameters")
void findIndices(int[] expectedNumbers, int[] inputNumbers, int target) {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
private static Stream<Arguments> parameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6),
Arguments.of(new IllegalArgumentException("No two sum solution"), new int[]{3, 1, 2}, 6));
}
}
虽然前 3 个测试通过了,但我在第 4 个参数中收到以下错误消息:
org.junit.jupiter.api.extension.ParameterResolutionException:在索引 0 处转换参数时出错:没有将类型 java.lang.IllegalArgumentException 的对象转换为类型 [I
的隐式转换什么是更好的测试方法?
你可以做这样的事情,或者可能只是对抛出异常的情况进行单独的测试。
@ParameterizedTest
@MethodSource("parameters")
void findIndices(int[] expectedNumbers, int[] inputNumbers, int target, Class expectedException) {
if (expectedException != null) {
assertThrows(expectedException, () -> twoSumCalculator.twoSum(inputNumbers, target));
} else {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
}
private static Stream<Arguments> parameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6, null),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9, null),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6, null),
Arguments.of(null, new int[]{3, 1, 2}, 6, IllegalArgumentException.class));
}
与其尝试在同一测试中对成功和失败案例进行参数化,我建议您分别进行测试。这使您可以使用 assertThrows
方法断言抛出的异常,并避免在测试代码中引入逻辑。
类似于:
class TwoSumCalculatorTest {
TwoSumCalculator twoSumCalculator = new TwoSumCalculator();
@ParameterizedTest
@MethodSource("twoSumParameters")
void twoSumSolutions(int[] expectedNumbers, int[] inputNumbers, int target) {
int[] resultedNumbers = twoSumCalculator.twoSum(inputNumbers, target);
assertArrayEquals(expectedNumbers, resultedNumbers);
}
@ParameterizedTest
@MethodSource("noTwoSumParameters")
void noTwoSumSolutions(int[] inputNumbers, int target) {
assertThrows(IllegalArgumentException.class, () -> {
twoSumCalculator.twoSum(inputNumbers, target);
})
}
private static Stream<Arguments> twoSumParameters() {
return Stream.of(
Arguments.of(new int[]{1, 2}, new int[]{3, 2, 4}, 6),
Arguments.of(new int[]{0, 1}, new int[]{2, 7, 11, 15}, 9),
Arguments.of(new int[]{0, 1}, new int[]{3, 3}, 6)
);
private static Stream<Arguments> noTwoSumParameters() {
return Stream.of(
Arguments.of(new int[]{3, 1, 2}, 6)
// Could add more exceptional cases here
);
}