On the use of reflection in testing and not only
- Tutorial
For many, reflection is associated with bloated code or incorrectly designed api.
Under the cat are some useful examples that will show the positive aspects of reflection.
We will train onducks sortings.
Immediately imagine the situation that we want to study a lot of sortings, we want all of them to work and be tested.
However, we are too lazy to write tests for all algorithms. Therefore, we will only test the ISort interface, and all other classes, as if by themselves, will be tested)
Well, that’s all, now you can officially announce the victory of laziness.
Sorting testing will now be reduced to creating such classes
A similar approach is used, for example, in Spring Data.
And also in other places that we don’t even know about.
Under the cat are some useful examples that will show the positive aspects of reflection.
We will train on
public interface ISort {
int[] sort(int[] ints);
}
public class MergeSort implements ISort {
// Реализация сортировки
}
public class QuickSort implements ISort {
// Реализация сортировки
}
Immediately imagine the situation that we want to study a lot of sortings, we want all of them to work and be tested.
However, we are too lazy to write tests for all algorithms. Therefore, we will only test the ISort interface, and all other classes, as if by themselves, will be tested)
// Делаем тест в виде шаблона
public abstract class ISortTest {
private Class aClass;
private T sortAlgorithm;
public ISortTest() {
// Получаем тип дженерика заданного в шаблоне
aClass = Optional.of(getClass())
.map(Class::getGenericSuperclass)
.filter(el -> el instanceof ParameterizedType)
.map( el -> (ParameterizedType) el)
.filter(el -> el.getActualTypeArguments().length > 0)
.map(el -> el.getActualTypeArguments()[0])
.filter(el -> el instanceof Class)
.map(el -> (Class) el)
.orElse(null);
}
@BeforeEach
void init() throws IllegalAccessException, InstantiationException {
// Получаем экземпляр конкретной сортировки
sortAlgorithm = aClass.newInstance();
}
@Test
void sortTest() {
assertNotNull(sortAlgorithm);
int n = 10000;
int[] ints = new Random().ints().limit(n).toArray();
int[] sortInts = Arrays.stream(ints)
.sorted()
.toArray();
int[] testSotrInts = sortAlgorithm.sort(ints);
assertArrayEquals(sortInts, testSotrInts);
}
}
Well, that’s all, now you can officially announce the victory of laziness.
Sorting testing will now be reduced to creating such classes
class MergeSortTest extends ISortTest {
// Тут ничего нет
}
class QuickSortTest extends ISortTest {
// Тут ничего нет
}
A similar approach is used, for example, in Spring Data.
public interface TestRepository extends CrudRepository {
}
And also in other places that we don’t even know about.