【问题标题】:Repository in @DataJpaTest initialized to null@DataJpaTest 中的存储库初始化为 null
【发布时间】:2019-01-09 10:49:48
【问题描述】:

我正在尝试在我的 Spring Boot 应用程序中为存储库编写一些测试,但是存储库被自动装配为 null。测试类的代码如下:

package jpa.project.repo;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ContextConfiguration;

import jpa.project.entity.Person;

@EnableAutoConfiguration
@ContextConfiguration(classes = PersonRepo.class)
@DataJpaTest
public class PersonRepoTest {

    @Autowired
    private PersonRepo personRepoTest;

    @Test
    public void testPersonRepo() throws Exception {

        Person toSave = new Person();
        toSave.setPersonId(23);

        if (personRepoTest == null) {
            System.out.println("NULL REPO FOUND");
        }

        personRepoTest.save(toSave);

        Person getFromDb = personRepoTest.findOne(23);

        Assert.assertTrue(getFromDb.getPersonId() == 23);
    }
}

当我在 Eclipse 中将此文件作为 JUnit 测试运行时,打印语句确实会打印出来,这确认了随后出现的 nullpointerexception。我所有的测试都在与主应用程序相同的包中,但这些包位于 src/test/java 下。我尝试对包装名称进行一些更改,但这没有帮助,所以我不知道现在是什么问题。为什么repo初始化为null?

【问题讨论】:

  • 我认为你需要在 personRepoTest 为空时返回?由于您的if 条件将执行,而且personRepoTest.save(toSave) 行似乎是NullPointerException。
  • @gtgaxiola print 语句只是为了确认它为空,但问题是它为什么为空(编辑问题以更好地反映这一点)?
  • 你为什么不用@RunWith(SpringRunner.class) @DataJpaTest
  • @DirkDeyne 我以前有过,但我收到了Failed to load ApplicationContext 错误
  • @ITWorker 是的...请注意上面的测试类缺少@RunWith(SpringRunner.class)

标签: java spring-boot junit spring-data-jpa spring-test


【解决方案1】:

使用像 @DataJpaTest 这样的测试切片时的问题是 Spring Boot 只会加载一组特定的类。请参阅 Spring 文档中的这一部分:

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

@Repository 被认为是常规的 @Component,因为它不是 Spring Data JPA 存储库(接口是)。所以,它没有加载。默认情况下只会加载存储库接口,如下所示:

public interface PersonRepo extends JpaRepository<Person, Long> {
    ...
}

要解决您的问题,您可以强制 @DataJpaTest 加载所有 @Repository 类:

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

或者只是将您需要的@Repository 类导入到您的测试中:

@Import(PersonRepo.class)

这是另一个类似的问题:Spring test with @DataJpaTest can't autowire class with @Repository (but with interface repository works!)

【讨论】:

【解决方案2】:

这是一个使用 @DataJpaTest 和 TestEntityManager 进行单元测试的工作示例:

PersonRepo 扩展了 JpaRepository 并具有 @Repository 注释

我在我的项目中使用这种方法,如果你的所有配置都有效并且应用程序可以正常运行,那么测试就会通过。

@RunWith(SpringRunner.class)
@DataJpaTest
public class RepositoryTest {

    @Autowired
    TestEntityManager entityManager;

    @Autowired
    PersonRepo sut;

    @Test
    public void some_test() {
        Person toSave = new Person();
        toSave.setPersonId(23);

        entityManager.persistAndFlush(toSave);

        Person getFromDb = sut.findOne(23);
        Assert.assertTrue(getFromDb.getPersonId() == 23);
    } 
}

【讨论】:

  • 我在发布问题之前尝试了这种方法,但它不起作用(关于需要在主应用程序中自动装配的服务的错误)。我的应用程序有一个调度程序,所以我按照这个 SO 线程作为我尝试的基础:stackoverflow.com/questions/50231209/…
猜你喜欢
  • 2016-04-12
  • 2021-12-06
  • 2016-07-30
  • 2011-07-06
  • 2019-03-22
  • 1970-01-01
  • 2015-04-02
  • 2017-04-06
相关资源
最近更新 更多