Ошибка при тестировании
При выполнении этой части кода:
final String testCases = MethodSourceParametrizedTesting.testCases()
.map(arg -> Arrays.stream(arg.get()).map(Object::toString).collect(joining(",")))
.collect(joining(";"));
Возникает следующая ошибка:
java: cannot find symbol
symbol: method map((arg)->Arr[...]",")))
location: interface java.lang.String[][]
Сам тест:
class MethodSourceParametrizedTesting {
Factorial factorial = new Factorial();
public static String[][] testCases() {
return new String[][]{
{"1","1"}, {"2", "2"}, {"5", "120"}};
}
@ParameterizedTest
@MethodSource("testCases")
void testFactorial(String in, String expected) {
assertEquals(expected, factorial.factorial(in));
}
}
Ответы (1 шт):
Ошибка №1
java: cannot find symbol
symbol: method map((arg)->Arr[...]",")))
location: interface java.lang.String[][]
Он ругается на то, что вы пытаетесь вызвать метод map сразу на результате testCases()
Результатом вызова которого является двумерный массив и он такого метода не имеет
Его нужно обернуть Arrays.stream() и потом уже вызывать map()
Arrays
.stream(MethodSourceParametrizedTesting.testCases())
.map( /** ... */);
Ошибка №2
map(arg -> Arrays.stream(arg.get()) // ...
В данном случае лямбда получает на вход String[]
И опять же, массив не имеет метода get()
Тут мы просто убираем get() и передаем arg в stream() как есть
stream(arg)
Рабочий пример
final String testCases = Arrays.stream(MethodSourceParametrizedTesting.testCases())
.map(arg -> Arrays.stream(arg).map(Object::toString).collect(joining(",")))
.collect(joining(";"));
System.out.println(testCases);
out
1,1;2,2;5,120
UPDATE
возвращаем сразу Stream+Supplier
Так как мы не можем изменить
final String testCases = MethodSourceParametrizedTesting.testCases()
.map(arg -> Arrays.stream(arg.get()).map(Object::toString).collect(joining(",")))
.collect(joining(";"));
То нам нужно подстроиться так, чтобы у нас не возникало никаких ошибок.
- для того чтобы при вызове
testCases().map(/**...*/)не возникала ошибка нам следует не обернуть вызовtestCases()вArrays.stream(/**...*/), а сразу возвращать Stream изtestCases()... тогда map будет работать нормально - второй нашей проблемой был вызов
arg.get()
мы там имелиString[]на входе, но как известноString[], не имеет методаget()...
И подумав, что же они там могут ждать - я не придумал ничего лучше как функциональьный интерфейсSupplier, все что умеет который - это возвращать элементы с помощью методаget()
public static Stream<Supplier<String[]>> testCases() {
return (Stream<Supplier<String[]>>)IntStream.range(1, 6).mapToObj((i)->{
Integer current = i;
Supplier<String[]> item = () -> {
Integer result = 1;
for (int j = 1; j <= current ; j++) {
result = result * j;
}
String[] pair = { Integer.toString(current), Integer.toString(result)};
return pair;
};
return item;
}
);
}
Вывод:
1,1;2,2;3,6;4,24;5,120
Что соответствует факториалу
UPDATE 2
Замечание:
Если честно, то я старый дед и работал сJavaзадолго до выходаJDK 1.8и появленияStream'ов
Знаю я их потольку-поскольку и не могу сказать что они прям очень плотно засели в моем арсенале, поэтому если что-то можно было сделать эффективнее и элегантнее - не серчайте
когда начал писать объяснения, понял, что лучше упростить все до нЕльзя - и Вам понятнее будет, и проще, и практичнее.
я вернулся к старому варианту без итераторов, генераторов и прочего...чтобы все можно было статично задать и получить.
Собственно вся хитрость просто в том, что я
- взял заранее определенный двумерный массив
- сделал стрим на основе этого массива
- и смапил
Stream<String[]>который в качестве элементов имеет массив строк, вStream<Supplier<String[]>>стрим каждый из элементов которого может получить массив строк с помощью функционального интерфейсаSupplier<T>
Для последнего нужно просто вызвать метод map() и передать туда лямбду, которая будет приводить массив строк String[] в лямбду Supplier<String>
Делаем мы это так:
// получаем на вход String[] pair
pair -> {
// Объявляем лямбду, единственной задачей которой, является возвращение pair
Supplier<String[]> item = () -> pair;
// возвращаем не pair, а лямбду, которая уже сможет вернуть pair
// запутанно? - да!
// а что вы хотели? такое условие задания
return item;
}
И уже рабочий вариант метода:
public static Stream<Supplier<String[]>> testCases() {
String[][] cases = new String[][]{
{"1","1"}, {"2", "2"}, {"5", "120"}
};
return Arrays.stream(cases).map(pair -> {
Supplier<String[]> item = () -> pair;
return item;
});
}
Вывод:
1,1;2,2;5,120