Spring @DataJpaTest 与 JUnit 5

Posted

技术标签:

【中文标题】Spring @DataJpaTest 与 JUnit 5【英文标题】:Spring @DataJpaTest with JUnit 5 【发布时间】:2019-10-06 10:57:09 【问题描述】:

我在网上似乎没有一种特定的标准方法可以使@DataJpaTest 正确运行。

@DataJpaTest 现在没有被使用,并且所有测试都使用@SpringBootTest 在服务或控制器级别运行,这是真的吗?

    @Repository
    public interface MyBeanRepository extends JpaRepository<MyBean, Long>  
    

    @Configuration
    @EnableJpaRepositories("com.app.repository.*")
    @ComponentScan(basePackages =  "com.app.repository.*" )
    public class ConfigurationRepository  
    


    @Entity
    public class MyBean 

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "id")
        private Long id;

        @Version
        @Column(name = "version")
        private Integer version;

        @NotNull
        @Size(min = 2)
        private String name;
    

    @DataJpaTest
    public class MyBeanIntegrationTest 

        @Autowired
        MyBeanRepository myBeanRepository;

        @Test
        public void testMarkerMethod() 
        

        @Test
        public void testCount() 
            Assertions.assertNotNull(myBeanRepository , "Data on demand for 'MyBean' failed to initialize correctly");
        
    

使用 Eclipse 运行->Run Junit 会显示这些日志。

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test
    at org.springframework.util.Assert.state(Assert.java:73)

使用gradle test运行显示init失败的错误。

FAILURE: Build failed with an exception.

* What went wrong:
Test failed.
    Failed tests:
        Test com.app.repository.MyBeanIntegrationTest#initializationError (Task: :test)

这是 gradle 脚本。

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin")
    


plugins 
    id 'org.springframework.boot' version '2.1.5.RELEASE'
    id 'java'
    id 'eclipse'



apply plugin: 'io.spring.dependency-management'

group = 'com.app'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories 
    mavenLocal()
    jcenter()
    mavenCentral()


test 
    useJUnitPlatform()


dependencies 
    // This dependency is exported to consumers, that is to say found on their compile classpath

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    runtimeOnly 'org.hsqldb:hsqldb'
    testImplementation ('org.springframework.boot:spring-boot-starter-test') 
        // exlcuding junit 4
        exclude group: 'junit', module: 'junit'
    

    /**
        Test Dependencies Follows
    **/


    // junit 5 api
    testCompile "org.junit.jupiter:junit-jupiter-api:5.2.0"
    // For junit5 parameterised test support
    testCompile "org.junit.jupiter:junit-jupiter-params:5.2.0"
    // junit 5 implementation
    testRuntime "org.junit.jupiter:junit-jupiter-engine:5.2.0"
    // Only required to run junit5 test from IDE
    testRuntime "org.junit.platform:junit-platform-launcher"


编辑:

这已在同一个存储库中解决并提交。 https://github.com/john77eipe/spring-demo-1-test

【问题讨论】:

如果您尊重标准包布局 (docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…),一切都应该正常。 代码在这里尝试:github.com/john77eipe/spring-demo-1-test @JBNizet 我找不到问题所在。 您在 com.app 包中没有任何使用 @SpringBootApplication 注释的主应用程序类。 存储库项目不会包含@SpringBootApplication 对吗?或者我们应该为此放一个。另外,如果这不是一个 Spring Boot 项目,而是一个 Spring 项目,有没有办法让它仅用于测试? 【参考方案1】:

添加一个 Github 链接是个好主意。我可以在那里看到以下问题:

1) 如果你不能有一个用@SpringBootApplication注解的主类,你可以使用:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.app.repository")
public class MySampleApplication 

2) 将 ConfigurationRepository 类的注释更改为:

@EnableJpaRepositories("com.app.repository")
@ComponentScan(basePackages =  "com.app.repository" )
public class ConfigurationRepository 

这应该让我们继续下一点:

3) 您的MyBeanIntegrationTest 应注释为:

@SpringBootTest(classes = MyAppApplication.class)
public class MyBeanIntegrationTest 

4) 在application.yml 中,最后一行的缩进有一个小问题。将制表符转换为空格,应该没问题。

5) 接下来是MyBeanRepository 接口。您不能在那里使用名为findOne 的方法。问题是,在标记为JpaRepositoryCrudRepository 等的接口中,方法名称需要遵循一定的规则。如果您将其标记为包含类型MyBean 的存储库,则您的方法名称应更改为findById,因为Spring 将在您的bean 中查找名为id 的属性。用findOne 命名它会导致测试失败:

No property findOne found for type MyBean!

修复这些问题后,您的测试通过了我的环境。

我希望这会有所帮助!

【讨论】:

@DataJpaTest 运行嵌入式数据库对吗? RunWith 适用于 JUnit 4。DataJpaTest 使用 ExtendWith(SpringExtension.class) 进行元注释。 mate00 我不应该使用@SpringBootApplication 我想我应该使用@ ContextConfiguration 知道怎么做吗? 哦,我没注意到你不能使用@SpringBootApplication。也许这就是为什么我被否决了这么多次:( 我用不同于@SpringBootApplication的注释更新了答案

以上是关于Spring @DataJpaTest 与 JUnit 5的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

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