【问题标题】:unable to launch spring-data-rest unit test, RepositoryRestResource not available for @Autowire无法启动 spring-data-rest 单元测试,RepositoryRestResource 不可用于@Autowire
【发布时间】:2017-03-29 15:45:31
【问题描述】:

我正在将一个应用程序从 JDBC / REST 移植到 spring-data-rest,而我的唯一一个单元测试失败并出现错误

NoSuchBeanDefinitionException: 
    No qualifying bean of type 'com.xxx.repository.ForecastRepository' available

该应用程序之前使用spring-boot 进行了改造,现在我正尝试在spring-data-jpa 之上使用spring-data-rest 放置一个新层。

我正在尝试根据

制定正确的 Java 配置

Custom Test Slice with Spring Boot 1.4

但我不得不偏离惯用的方法,因为

  1. @WebMvcTest 注释不会抑制导致测试失败的安全模块
  2. @MockMvcAutoConfiguration 由于缺少依赖关系而失败,除非我指定 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)(请参阅 here
  3. @WebMvcTest@SpringBootTest 是互斥的,因为它们都指定了 @BootstrapWith 并且不能一起运行

所以这是我最接近的,但 Spring 找不到我的 @RepositoryRestResource 存储库:

存储库

@RepositoryRestResource(collectionResourceRel = "forecasts", path = "forecasts")
public interface ForecastRepository extends CrudRepository<ForecastExEncoded,
        Long> {

JUnit 测试

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK,
        classes = {TestRestConfiguration.class})
public class ForecastRestTests {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ForecastRepository forecastRepository;

    @Before
    public void deleteAllBeforeTests() throws Exception {
        forecastRepository.deleteAll();
    }

    @Test
    public void shouldReturnRepositoryIndex() throws Exception {

        mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()).andExpect(
                jsonPath("$._links.forecasts").exists());
    }

}

配置

@OverrideAutoConfiguration(enabled = false)
@ImportAutoConfiguration(value = {
        RepositoryRestMvcAutoConfiguration.class,
        HttpMessageConvertersAutoConfiguration.class,
        WebMvcAutoConfiguration.class,
        MockMvcAutoConfiguration.class,
        MockMvcSecurityAutoConfiguration.class
})
@Import({PropertySpringConfig.class})
public class TestRestConfiguration {}

也试过了...

我试图用@WebMvcTest 和下面的How to exclude AutoConfiguration from Spring Boot 中的@ComponentScan 来配置单元测试,试图简化这一切,但是excludeFilters 没有效果。

@ComponentScan(
        basePackages="com.xxx",
        excludeFilters = {
                @ComponentScan.Filter(type = ASSIGNABLE_TYPE,
                        value = {
                                SpringBootWebApplication.class,
                                JpaDataConfiguration.class,
                                SecurityConfig.class
                        })
        })

我已将 Spring 的日志记录设置为跟踪,因为此时我所能做的就是尝试从日志输出中找到有关正在发生的事情的线索。到目前为止,虽然没有任何运气。

我可以在日志中看到 RepositoryRestConfiguration 正在加载,但显然它没有提供正确的信息,在谷歌搜索并倾注于 Spring 文档和 API 之后,我无法弄清楚这是如何完成的。我想我一定已经阅读了关于 SO 的所有相关问题。

2016-11-16 10:00更新

我在日志中看到的与我有关的一件事是:

Performing dependency injection for test context  [DefaultTestContext@2b4a2ec7 [snip...]
 classes = '{class com.xxx.TestRestConfiguration, 
    class com.xxx.TestRestConfiguration}', 

即上下文列出了配置类两次。我在 @SpringBootTest#classes 注释上指定了配置类(仅一次)。但是如果我从注解中去掉#classes,Spring Boot 会通过@SpringBootApplication 类找到并拉入所有配置。

那是不是暗示我在错误的地方指定了配置?不然怎么办?

【问题讨论】:

    标签: unit-testing junit spring-boot spring-data-rest spring-java-config


    【解决方案1】:

    经过太多时间,我决定采用这种方法。

    Custom Test Slice with Spring Boot 1.4 看起来很有希望,但我却一事无成。

    一遍又一遍

    Accessing JPA Data with REST

    我意识到我必须包含 JPA 设置,因为 spring-data-rest 直接使用它们 - 没有机会在没有嵌入式数据库的情况下模拟它们或运行单元测试。

    至少据我所知不是。也许可以模拟它们并让spring-data-rest 针对测试数据在模拟上运行,但我认为spring-data-restspring-data 可能过于紧密耦合。

    所以必须进行集成测试。

    在上面文章提供的Spring源码中

    gs-accessing-data-rest/ApplicationTests.java

    日志显示 Spring Boot 拉入应用程序上下文的整个配置。

    为了避免我的SpringBootApplication 类并且没有加载安全模块,我这样设置我的测试:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @ContextConfiguration(classes = {
            JpaDataConfiguration.class,
            TestJpaConfiguration.class,
            TestRestConfiguration.class,
            PropertySpringConfig.class})
    public class ForecastRestTests {
    
        @SuppressWarnings("SpringJavaAutowiringInspection")
        @Autowired
        private MockMvc mockMvc;
    
        @Autowired
        private ForecastRepository forecastRepository;
    
        @Before
        public void deleteAllBeforeTests() throws Exception {
            forecastRepository.deleteAll();
        }
    
        @Test
        public void shouldReturnRepositoryIndex() throws Exception {
    
            mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()).andExpect(
                    jsonPath("$._links.forecasts").exists());
        }
    
    }
    

    使用这些配置类:

    @Configuration
    @EnableJpaRepositories(basePackages = {"com.bp.gis.tardis.repository"})
    @EntityScan(basePackages = {"com.bp.gis.tardis.type"})
    public class JpaDataConfiguration {
    

    @Configuration
    @OverrideAutoConfiguration(enabled = false)
    @ImportAutoConfiguration(value = {
            CacheAutoConfiguration.class,
            JpaRepositoriesAutoConfiguration.class,
            DataSourceAutoConfiguration.class,
            DataSourceTransactionManagerAutoConfiguration.class,
            HibernateJpaAutoConfiguration.class,
            TransactionAutoConfiguration.class,
            TestDatabaseAutoConfiguration.class,
            TestEntityManagerAutoConfiguration.class })
    public class TestJpaConfiguration {}
    

    @Configuration
    @OverrideAutoConfiguration(enabled = false)
    @ImportAutoConfiguration(value = {
            RepositoryRestMvcAutoConfiguration.class,
            HttpMessageConvertersAutoConfiguration.class,
            WebMvcAutoConfiguration.class,
            MockMvcAutoConfiguration.class,
            MockMvcSecurityAutoConfiguration.class
    })
    public class TestRestConfiguration {}
    

    所以 TL;DR 总结是:使用@ContextConfiguration 来指定指定@OverrideAutoConfiguration@ImportAutoConfiguration 的配置文件

    【讨论】:

      猜你喜欢
      • 2016-04-17
      • 2018-11-14
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 1970-01-01
      • 2019-12-18
      相关资源
      最近更新 更多