Как написать @SpringBootTest для приложения с репозиториями @ComponentScan и JPA - PullRequest
0 голосов
/ 13 февраля 2019

Мне очень трудно писать @SpringBootTest, если вы используете репозитории @ComponentScan и Jpa.Может кто-нибудь посоветовать?Это должно быть очень тривиально, но это нигде не задокументировано.

@SpringBootApplication  
@ComponentScan(
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) },
        basePackageClasses = {Main.class, Other.class})
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

и один из обнаруженных классов конфигурации имеет:

@Configuration
@EnableJpaRepositories("jpa")

Теперь я хочу создать тест, который позволитв идеале это просто подмножество репозиториев JPA и ничего более, если я не скажу так.А именно, нет конфигурации из производственного исходного кода.Кажется, это почти невозможно выразить.Вот где я смог получить:

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(TestIT.TestConfig.class)
public class TestIT {

    @Configuration
    @EnableJpaRepositories("jpa")
    @AutoConfigureDataJpa
    @AutoConfigurationPackage
    public static class TestConfig {
        //here will be beans for test.
    }

, поэтому эта конфигурация выдает ошибку

java.lang.IllegalArgumentException: Not a managed type ...my jpa repository class

, что, вероятно, означает, что пакет jpa несреди автоматически настроенных пакетов.Не знаю, как добавить его, если это возможно.

ОК, другой подход.Некоторые источники рекомендуют это:

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(TestIT.TestConfig.class)
public class TestIT {

    EnableJpaRepositories("jpa")
    @EntityScan(basePackages = "jpa.entities")
    //@TestPropertySource("classpath:application.properties")
    @EnableTransactionManagement
    public static class TestConfig {
        //here will be beans for test.
    }

, но этот сбой с caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!

Любые подсказки?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

ОК, после долгих поисков (тщетно) и даже больше попыток, я думаю, у меня есть ответ.

Подводя итог:

у вас есть основной класс (спасибо @Bhushan Shinde):

@SpringBootApplication(scanBasePackageClasses = {Main.class, Other.class})
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

и некоторые настройки:

@Configuration
@EnableJpaRepositories("jpa")
public class Config

Итак, чтобы использовать SpringBootTest и настроить все с нуля для тестирования, игнорируя производственные конфигурации, вы идете:

@RunWith(SpringRunner.class)
@SpringBootTest(
        webEnvironment = SpringBootTest.WebEnvironment.NONE,
        classes = TestIT.TestConfig.class)
//@Import(TestIT.TestConfig.class)
public class TestIT {

    @Configuration
    @AutoConfigureDataJpa
    @EnableJpaRepositories("jpa") //fake package names, obviously
    @EntityScan(basePackages = "jpa.entities")
//    @TestPropertySource("classpath:application.properties")
    @EnableTransactionManagement
    public static class TestConfig {
         //test related beans & config.
    }

    //tests here.
}

может быть, здесь есть что-то еще, но после дня поисков и попыток это достаточно для меня.

0 голосов
/ 13 февраля 2019

Прежде всего, нет особой необходимости добавлять @ComponentScan в файл запуска вашего основного приложения.@SpringBootApplication достаточно.

Теперь о тестовых случаях: я использую powermockito, все мои тестовые примеры обычно выглядят так: -

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PrepareForTest({ ContextProvider.class, ConfigurationUtils.class, Utils.class })
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestIT {

В предложении @PrepareForTest упоминаются все классычто вы бы упомянули с аннотацией @Mock.Например, нет необходимости упоминать какие-либо интерфейсы репо (интерфейсы уровня DAO, где мы пишем наши запросы).Таким образом, объявление вашего репо будет выглядеть так:

private SoftwareRepo softwareRepo;

И вы будете использовать его, пока выполняется

softwareInventoryRepo = PowerMockito.mock(SoftwareRepo.class);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...