Обработка исключений с помощью @MethodSource

#java #arrays #junit5 #illegalargumentexception

#java #массивы #junit5 #исключение illegalargumentexception

Вопрос:

Я только начал выполнять упражнение под названием «Two Sum» в LeetCode, и у меня возникли проблемы с тестированием.

Теперь код для упражнения выглядит следующим образом:

 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

Какой был бы лучший способ проверить это?

Ответ №1:

Вместо того, чтобы пытаться параметризовать как успешные, так и неудачные случаи в одном и том же тесте, я бы посоветовал вам протестировать их отдельно. Это позволяет использовать 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
        );
    }
  

Ответ №2:

Вы могли бы сделать что-то подобное или, возможно, просто провести отдельный тест для случаев, которые вызывают исключения.

     @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));
    }