Во время рефакторинга юнит-тестов наткнулся на очень интересную и полезную фичу JUnit-а (начиная с версии 4.4): Теория (Theory).

Обычно, когда тестируется некий функционал пишется большое количество тестов, которые проверяют работу кода в зависимости от разных наборов входных данных. При этом код самого теста не меняется. Все это вырождается в тест-кейс состоящий из десятка идентичных методов.

Теории, позволяют задать набор данных, для которых должен выполнится тест.

Ниже приведен кусок кода без использования теорий:

public class TestWithoutTheory
{
    @Test
    public void testStringA()
    {
        String s = "A";
        callSomeBusinessLogic(s);

        // asserts go here
    }

    @Test
    public void testStringB()
    {
        String s = "B";
        callSomeBusinessLogic(s);

        // asserts go here
    }

    @Test
    public void testStringC()
    {
        String s = "C";
        callSomeBusinessLogic(s);

        // asserts go here
    }
}

Как видно, методы отличаются только набором данных, который передается в метод callSomeBusinessLogic.
Объединить все это в один метод было бы неправильно, так как если ошибка произойдет при использования одного из наборов данных, зафейлится весь тест, что неправильно.

Решить данную проблему поможет Теория (Theory). Ниже приведен тест переписанный при помощи теории:

@RunWith(Theories.class)
public class TestWithTheory
{
    public static @DataPoints String[] values = {"A", "B", "C"};

    @Theory
    public void testString(String s)
    {
        callSomeBusinessLogic(s);

        // asserts go here
    }
}

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