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 on ducks sortings.

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.

Also popular now: