Junit的春天避免两次加载应用程序上下文的数据源

问题描述 投票:0回答:4

我有这样的配置类:

@ComponentScan(
        basePackages = { 
                "mypackage.controller",
                "mypackage.service",
                "mypackage.repository" 
        }
)
@TestPropertySource(locations="classpath:configuration.properties")
@Import({
    H2Configuration.class
})
public class TestConfiguration {
}

@Configuration
public class H2Configuration {

    @Bean
    public DataSource dataSource() throws SQLException {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        EmbeddedDatabase db = builder
                .setType(EmbeddedDatabaseType.H2)
                .addScript("h2/create.sql")
                .addScript("h2/insert.sql")
                .build();
        db.getConnection().setAutoCommit(false);
        return db;
    }

}

我有这两类测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes = { TestConfiguration.class })
public class FirstRepositoryTest {

    @Autowired
    MyFirstRepositoryImpl repository;

    @Before
    public void initTest() {
    }

    @Test(expected = NullPointerException.class)
    public void testNullRecords() {
        repository.foo(null, null);
    }
}


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes = { TestConfiguration.class })
public class SecondRepositoryTest {

    @Autowired
    MySecondRepositoryImpl repository;

    @Before
    public void initTest() {
    }

    @Test(expected = NullPointerException.class)
    public void testSomethingNullRecords() {
        repository.something(null, null);
    }
}

如果我为每个类运行JUnit测试一次,一切顺利。

在全新安装阶段测试失败,因为应用程序上下文被初始化两次。

例如,它尝试两次创造H2表和做则将insert.sql脚本两次。

我要做的只有一次初始化数据库H2等应用程序上下文?

谢谢

java spring applicationcontext
4个回答
3
投票

我想你可以开始寻找关于Integration Testing Spring文档。

它也可以用于集成测试的事务测试(@Transactional),其回滚在每次测试结束一个很好的做法:看Transaction Management

ApplicationContext:为了避免重新创建为每个测试类Context Caching的成本,因为这里解释可以使用缓存。

对于嵌入式数据库集成测试,你还可以找到文档:Testing Data Access Logic with an Embedded Database。从以前的链接的说明,符合你的使用情况:

但是,如果你想创建一个测试套件内共享的嵌入式数据库,可以考虑使用Spring TestContext框架,并通过使用Spring XML和创建在创建嵌入式数据库说明配置了嵌入式数据库在Spring的ApplicationContext一个bean嵌入式数据库编程。

我希望你能找到一些有用的参考。


2
投票

在单元测试必须garantee每个测试是独立repeatible汉​​斯上下文。由于这不加载上下文只有一次不错的主意。为更好地执行后复位。为此,您可以在您的测试类使用@DirtiesContext(classMode = ClassMode.AFTER_CLASS)

所以,你会强迫你的情况下重新启动下一个JUnit类启动


2
投票

另一个很好的提示,我从春天启动文件发现从Embedded Database Support

他们说 :

如果您使用的是你的测试此功能,您可能会注意到,同样的数据库是由你的整个测试套件,无论您使用的应用程序上下文的数量的重复使用。如果你想确保每个方面都有一个独立的嵌入式数据库,你应该设置spring.datasource.generate唯一名称为true。

因此,为了使每个EmbeddedDatabase独特,您可以尝试与创建它们:

EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
                      .generateUniqueName(true)
                      ...
                      .build();

1
投票

所以,这是失败的原因是数据库(H2)是驻留在内存中,当您运行测试作为清洁部分/安装。运行第一次测试后,创建/插入脚本已经执行。这点之后的任何后续测试执行将导致在同一个脚本(或多个),并且将发生该错误的重新执行。

更新您创建脚本以DROP TABLE IF EXISTS <table name>;。这将确保该表被删除,然后重新创建。

注:我不知道为什么你明确指定AnnotationConfigContextLoader。我想,没有这个,亚军SpringJUnit4ClassRunner将缓存是没有改变的背景下。我不知道具体是,如果是这样的话,虽然在这里。

© www.soinside.com 2019 - 2024. All rights reserved.