如何使用@ComponentScan 和 JPA 存储库为应用程序编写 @SpringBootTest

How to write @SpringBootTest for app with @ComponentScan and JPA repositories

如果使用@ComponentScan 和Jpa 存储库,我发现编写@SpringBootTest 非常困难。有人可以建议吗?这应该是非常微不足道的东西,但它没有在任何地方记录。

@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!

有什么提示吗?

首先,没有特别需要在你的主应用程序启动文件中添加@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 提到的。 例如 无需提及任何 repo(我们编写查询的 DAO 层接口)接口。所以你的回购声明就像:

private SoftwareRepo softwareRepo;

你会在执行时使用它

softwareInventoryRepo = PowerMockito.mock(SoftwareRepo.class);

好的,经过大量的搜索(徒劳的)和更多的尝试,我想我找到了答案。

回顾一下:

你有主要的class(感谢@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.
}

也许这里有一些额外的东西,但经过一天的谷歌搜索和尝试,这对我来说已经足够了。