簡體   English   中英

Junit Spring 避免加載兩次應用程序上下文數據源

[英]Junit Spring avoid to load twice application context datasource

我有這個配置類:

@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 數據庫和應用程序上下文一次?

謝謝

我認為您可以開始查看有關集成測試的 Spring 文檔。

將事務測試用於集成測試 ( @Transactional ) 也是一個很好的做法,它在每個測試結束時回滾:請參閱事務管理

為了避免為每個測試類重新創建ApplicationContext的成本,可以按照此處的說明使用緩存上下文緩存

對於嵌入式數據庫的集成測試,您還可以找到文檔: 使用嵌入式數據庫測試數據訪問邏輯 來自上一個鏈接的注釋,與您的用例相匹配:

但是,如果您希望創建在測試套件內共享的嵌入式數據庫,請考慮使用 Spring TestContext Framework 並將嵌入式數據庫配置為 Spring ApplicationContext 中的 bean,如使用 Spring XML 創建嵌入式數據庫和創建嵌入式數據庫中所述以編程方式嵌入數據庫。

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

我從嵌入式數據庫支持的Spring Boot文檔中發現的另一個好技巧:

他們說 :

如果您在測試中使用此功能,您可能會注意到,無論您使用多少應用程序上下文,整個測試套件都會重用同一個數據庫。 如果要確保每個上下文都有單獨的嵌入式數據庫,則應將 spring.datasource.generate-unique-name 設置為 true。

因此,為了使每個EmbeddedDatabase獨一無二,您可以嘗試使用以下命令創建它們:

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

在單元測試中,您必須保證每個測試都是可重復的,並且與上下文無關。 因此,僅加載一次上下文並不是一個好主意。 執行后最好復位。 為此,您可以在測試類中使用@DirtiesContext(classMode = ClassMode.AFTER_CLASS)

因此,當啟動下一個 junit 類時,您將強制您的上下文重新啟動

因此,失敗的原因是當您將測試作為清理/安裝的一部分運行時,數據庫 (H2) 駐留在內存中。 創建/插入腳本在第一個測試運行后已經執行。 在此之后的任何后續測試執行都將導致重新執行相同的腳本並且會發生錯誤。

使用DROP TABLE IF EXISTS <table name>;更新您的創建腳本DROP TABLE IF EXISTS <table name>; . 這將確保該表被刪除然后重新創建。

注意:我不確定您為什么明確指定AnnotationConfigContextLoader 我認為,沒有它,運行程序SpringJUnit4ClassRunner將緩存尚未更改的上下文。 我不知道具體是否是這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM