Тестируйте Spring-бины с различными аргументами конструктора через JUnit, используя @ContextConfiguration - PullRequest
1 голос
/ 15 марта 2019

Описание проблемы:


Я бы хотел, чтобы пользователи настраивали Spring bean-файлы с помощью пользовательских конфигурационных файлов поверх Spring XML-конфигураций, например так: Обратите внимание, что пользователь должен настраивать только Strings, все остальные bean-компоненты должны быть @Autowired без ведома пользователя!

<bean class="com.my.group.Provider">
    <constructor-arg value="config1.proprietary"/>
    <constructor-arg value="config2.proprietary"/>
</bean>

Объект Provider выглядит (упрощенно) следующим образом:

public class Provider {
    @Autowired
    private Foo foo;
    private final String[] configNames;

    public Provider(final String... configs) {
        this.configNames = Preconditions.checkNotNull(configs, "Provided configs must not be null!");
    }

    public List<Configs> getConfigs() {
         return new foo.create(configNames); // here is more logic that I would actually like to test... (not just methods called on foo)
    }
}

Мой вопрос:

Как я могу протестировать это решение с различными строковыми входами, чтобы все тесты могли входить в один класс JUnit Test? Кстати: я бы хотел избежать отражений ...

(Модульные тесты ниже показывают, что я имею в виду. И они уже способны делать то, что я хочу, но они используют отражения.)


Что я сделал до сих пор

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ProviderTest.MyContext.class})
public class ProviderTest {

    @Autowired
    private Provider sut;

    @Test
    public void provide_oneConfig() throws NoSuchFieldException, IllegalAccessException {
        setConfigFilesViaReflection(sut, "config1.proprietary"");
        // When
        List<Config> configs = sut.getConfigs();

        // Then
        assertEquals(1, configs.size());
    }

    @Test
    public void provide_twoConfigs() throws NoSuchFieldException, IllegalAccessException {
        setConfigFilesViaReflection(sut, "config1.proprietary", config2.proprietary");
        // When
        List<Config> configs = sut.getConfigs();

        // Then
        assertEquals(2, configs.size());
    }

    private void setConfigFilesViaReflection(final Provider sut, final String... configs) throws NoSuchFieldException,
            IllegalAccessException {
        Field configNamesField = Provider.class.getDeclaredField("configNames");
        configNamesField.setAccessible(true);
        configNamesField.set(sut, configs);
    }

    @Configuration
    public static class MyContext {
        @Bean
        Provider provider() {
            return new Provider("willBeOverridenByReflection");
        }

        @Bean
        Foo foo() {
            return new Foo(); // this one got mocked in my test
        }
}

1 Ответ

1 голос
/ 15 марта 2019

Иногда задавание вопросов помогает искать сложнее.

Аннотация @Qualifier / @Resource позволяет создавать несколько бинов и выбирать их для каждого теста следующим образом:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ProviderTest.MyContext.class})
public class ProviderTest {

    @Autowired
    @Qualifier("bar") // could also be @Resource (without @Autowired)
    private Provider sut;
    @Resource(name="baz")
    private Provider sut2; // could also be @Qualifier(with @Autowired)

    @Test
    public void provide_oneConfig() throws NoSuchFieldException, IllegalAccessException {
        // When
        List<Config> configs = sut.getConfigs();

        // Then
        assertEquals(1, configs.size());
    }

    @Test
    public void provide_twoConfigs() throws NoSuchFieldException, IllegalAccessException {
        // When
        List<Config> configs = sut2.getConfigs();

        // Then
        assertEquals(2, configs.size());
    }

    @Configuration
    public static class MyContext {
        @Bean("bar")
        Provider providerBar() {
            return new Provider"config1.proprietary");
        }
        @Bean("baz")
        Provider providerBaz() {
            return new Provider("config1.proprietary", "config2.proprietary");
        }

        @Bean
        Foo foo() {
            return new Foo(); // this one got mocked in my test
        }
}

Нашел мой ответ здесь: Автопроводка двух разных бобов одного класса

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