【问题标题】:How autowire a repository in an integration test with Spring Boot?如何在使用 Spring Boot 的集成测试中自动装配存储库?
【发布时间】:2017-08-02 20:58:09
【问题描述】:

我正在尝试编写集成测试,但在测试中自动装配存储库时遇到问题。

我收到此异常: org.springframework.beans.BeanInstantiationException: 无法实例化 [org.observer.media.repository.ArticleRepository]: 指定的类是一个接口。

编辑: 我用@EnableJpaRepositories 添加了PersistenceConfig.class,代码如下。这导致异常org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

我还尝试在 @SpringBootTest(classes = {} 中添加 Application.class 以尝试全部捕获但抛出 Error creating bean with name 'articleRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class org.observer.media.model.Article

ScraperRunnerIntegrationTest(配置类只包含域类的bean):

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {
        ApplicationConfig.class,
        PersistenceConfig.class,
        DeMorgenTestConfig.class,
        Article.class,
        ScraperRunner.class,
        DeMorgenWebsiteScraper.class,
        ArticleService.class,
        DeMorgenPageScraper.class,
        JsoupParser.class,
        DeMorgenArticleScraper.class,
        GenericArticleScraper.class,
        ImageMetaScraper.class,
        ArticlePrinter.class,
        ArticleRepository.class
})
public class ScraperRunnerIntegrationTest {

    private final static Article EXPECTED_ARTICLE_1 = anArticle().withHeadline("headline1").build();
    private final static Article EXPECTED_ARTICLE_2 = anArticle().withHeadline("headline2").build();

    @Autowired
    private ScraperRunner scraperRunner;
    @Autowired
    private DeMorgenWebsiteScraper deMorgenWebsiteScraper;

    @Autowired
    private ArticleRepository articleRepository;

    @Test
    public void run() {
        scraperRunner.run(deMorgenWebsiteScraper);

        assertThat(articleRepository.findAll()).containsOnly(EXPECTED_ARTICLE_1, EXPECTED_ARTICLE_2);
    }

存储库:

import org.observer.media.model.Article;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {

    List<Article> findAll();

    Article findByHash(String hash);

    Article findByHeadline(String headline);

    List<Article> findArticleByHeadlineAndCompanyName(String headline, String companyName);

    @Query("SELECT CASE WHEN COUNT(a) > 0 THEN true ELSE false END FROM Article a WHERE a.hash = :hash")
    boolean existsByHash(@Param("hash") String hash);
}

PersistenceConfig.class:

package org.observer.media.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories("org.observer.media.repository") 
public class PersistenceConfig {
}

【问题讨论】:

  • 你的@Configuration 类中有@EnableJpaRepositories 注释吗?
  • 在这段代码中没有明确定义。不过,我已经尝试过该注释,并在那一刻得出结论,它不是罪魁祸首,并认为该注释包含在 SpringBootTest 注释中。不过我可能错了,稍后当我把代码放在我面前时,我会把注释放回去。我相信它然后抱怨没有我认为应该由 Spring Boot 自动配置的 EntityManagerFactory。然后我提供了一个带有数据源和 emf 等的配置,然后它又回到了与这篇文章中相同的错误。
  • @mp_loki 我添加了注解 EnableJpaRepositories,在问题中查看我的编辑

标签: java testing spring-boot repository autowired


【解决方案1】:

您只需要提供类,注释为@Configuration@SpringBootTest

我已将 here 的原始示例修改为使用 @SpringBootTest 注释。 所以以下配置有效:

@Configuration
@ComponentScan("hello")
public class AppConfig {

}

注意@ComponentScan 注释。 然后在我的测试中:

@RunWith(SpringRunner.class)
@SpringBootTest(classes={AppConfig.class})
public class CustomerRepositoryTests {
     @Autowired
     private CustomerRepository customerRepository;
}

它做了一个伎俩。你可以尝试在你的例子中做同样的事情。

【讨论】:

  • 我尝试了你的建议,但抛出了 Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'propertyPlaceholderAutoConfiguration' for bean class [org.springframework.boot.autoconfigure.context. PropertyPlaceholderAutoConfiguration] 与现有的、不兼容的相同名称和类的 bean 定义冲突 [org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration]
  • 你的配置有问题,如果没有看到它,我无法推断到底是什么。我建议您尝试使用尽可能简单的配置,然后开始一一添加。或者将您的项目发布到 GitHub(如果可能并且不违反任何 NDA)并在此处分享链接。
  • 单独使用 SpringBootTest,没有 classes{...} 工作:它加载完整的 applicationContext,包括存储库。使用 classes{} 时,只加载了一小部分上下文,这更精简,但存储库没有通过。这带来了一个新问题:在集成测试的 bean 中自动装配测试依赖项。现在它将所有东西自动连接在一起,就好像它在正常运行一样。我尝试了不起作用的配置文件,但这是另一个问题。我现在有一个工厂来创建测试依赖项,因为我今天不能再处理 S​​pring 了 :)
【解决方案2】:

我在集成测试中遇到了同样的异常org.springframework.beans.BeanInstantiationException:无法实例化[...]:指定的类是一个接口。 我在没有使用 PersistenceConfig.class 的情况下解决了问题,但只更改了我的集成类中使用的注释,这是错误的。我使用了以下注释: @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 因为我不想使用内存数据库。

您的代码可能如下:

@ComponentScan(basePackages = {"org.observer"})
@RunWith(SpringRunner.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@DataJpaTest
public class ScraperRunnerIntegrationTest {

    private final static Article EXPECTED_ARTICLE_1 = anArticle().withHeadline("headline1").build();
    private final static Article EXPECTED_ARTICLE_2 = anArticle().withHeadline("headline2").build();

    @Autowired
    private ScraperRunner scraperRunner;
    @Autowired
    private DeMorgenWebsiteScraper deMorgenWebsiteScraper;

    @Autowired
    private ArticleRepository articleRepository;

    @Test
    public void run() {
        scraperRunner.run(deMorgenWebsiteScraper);

        assertThat(articleRepository.findAll()).containsOnly(EXPECTED_ARTICLE_1, EXPECTED_ARTICLE_2);
    }

【讨论】:

    【解决方案3】:

    也许你可以试试@AutoConfigureDataJpa@AutoConfigureXxx 注释。

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 2018-02-19
      • 2016-10-10
      • 2018-02-15
      • 2017-07-17
      • 1970-01-01
      • 2020-09-27
      • 2017-03-28
      • 1970-01-01
      相关资源
      最近更新 更多