使用 @DataJpaTest 的 Spring 测试无法使用 @Repository 自动装配类(但使用接口存储库可以工作!)

Posted

技术标签:

【中文标题】使用 @DataJpaTest 的 Spring 测试无法使用 @Repository 自动装配类(但使用接口存储库可以工作!)【英文标题】:Spring test with @DataJpaTest can't autowire class with @Repository (but with interface repository works!) 【发布时间】:2018-06-29 01:09:17 【问题描述】:

我试图了解为什么我不能自动装配类存储库,但我可以为相同的测试自动装配相同包中的接口存储库。当我启动应用程序时,相同的存储库按预期工作。

首先,错误:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.app.person.repository.PersonRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true)
    at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.raiseNoMatchingBeanFound(DefaultPersonbleBeanFactory.java:1493)
    at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.doResolveDependency(DefaultPersonbleBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.resolveDependency(DefaultPersonbleBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 28 more

我有一个非常简单的例子。测试:

@RunWith(SpringRunner.class)
@DataJpaTest
public class PersonRepositoryTest 

    @Autowired
    private PersonRepository personRepository; // fail...

    @Autowired
    private PersonCrudRepository personCrudRepository; // works!

    @Test
    public void findOne() 
    

存储库类:

@Repository
public class PersonRepository 
    //code

仓库界面:

@Repository
public interface PersonCrudRepository extends CrudRepository<Person, Long> 

在bad experience with this same error 之后,我试图在我的配置中找到一些细节或测试导致此问题的原因。另一种可能性是@DataJpaTest 不支持类存储库。

【问题讨论】:

BTW 没有必要在你的界面中声明 Repository 注释。 Spring Data 创建的代理在幕后添加了一个,甚至是 Transactional 【参考方案1】:

我认为我对这个问题的看法是正确的。找到post on Github后阅读Spring Documentation:

如果您想测试 JPA 应用程序,可以使用@DataJpaTest。经过 默认它会配置一个内存嵌入式数据库,扫描 @Entity 类并配置 Spring Data JPA 存储库。常规的 @Component beans 不会被加载到 ApplicationContext 中。

我的PersonRepository 被认为是常规的@Component,因为它不是 Spring Data JPA 存储库(接口是)。所以,它没有加载。

替代解决方案是使用@SpringBootTest 而不是@DataJpaTest

此解决方案的缺点是会在运行测试时加载所有您的上下文,并因此禁用测试切片。但是做这项工作。

仍然使用@DataJpaTest 的另一个选项是包含@Repository 过滤器注释,如下所示:

@DataJpaTest(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Repository.class))

【讨论】:

嗨,我尝试了你的解决方案,但我仍然有同样的例外:***.com/questions/62313098/… 顺便说一句 - 关于“这个解决方案的缺点是会加载你所有的上下文”,你可以使用 SpringBootTestWebEnvironment.MOCK 来测试只有服务器端(与 Web 无关)。它当然会以某种方式降低性能的影响。【参考方案2】:

另一种选择可能是@Import,如此处所示https://***.com/a/41084739/384674。

【讨论】:

是的,我认为这是解决方案 这为我解决了同样的问题

以上是关于使用 @DataJpaTest 的 Spring 测试无法使用 @Repository 自动装配类(但使用接口存储库可以工作!)的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot:使用 @DataJpaTest 和 Flyway 设置 Hibernate 命名策略

Spring Boot 1.4 @DataJpaTest - 创建名为“dataSource”的 bean 时出错

@DataJpaTest 不会读取 spring.jpa.* 属性,而 @SpringBootTest 会

如何在使用 DataJpaTest 的 Spring Boot 2.0 测试中访问 H2 控制台

使用 @DataJpaTest 的 Spring 测试无法使用 @Repository 自动装配类(但使用接口存储库可以工作!)

在 JUnit 5 中使用 @TestContainers 实现 @DataJpaTest