2013-07-13 62 views
0

我有一系列的集成測試,我想測試我的彈簧mvc /彈簧數據jpa堆棧。不幸的是,構建時間很荒謬,而且每次新的集成測試只會變得更糟。它看起來就好像每個單獨的測試會通創建嵌入數據庫,bean創建等如何高效地創建基礎測試類的彈簧mvc集成測試

我有一個基礎測試類的開銷:

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

private static EmbeddedDatabase database; 

@BeforeClass 
public static void setUp() throws Exception { 
    database = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).setName("mydb") 
     .addScript("classpath:embeddedDatabase.sql").build(); 
} 


@Test 
    public void testInit() { 
     Assert.assertNotNull(database); 
    } 

凡我JpaConfig.java:

@Configuration 
@EnableTransactionManagement 
@ComponentScan(basePackages = { "org.myproject.service", "org.myproject.utility", 
     "org.myproject.controller", "org.myproject.utility.startup", 
     "org.myproject.security" }) 
@ImportResource({ "classpath:applicationContext.xml", "classpath:myproject-spring-security.xml" }) 
public class JpaConfig { 
@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {...} 
    @Bean 
    public DataSource dataSource() {...} 

    <etc> 
} 

然後最後我嘗試使用它,例如:

@TransactionConfiguration(defaultRollback = true) 
@Transactional(propagation = Propagation.NESTED) 
public class TestContactTypesIT extends BaseItegration { 

    @Autowired 
    private ContactTypeRefRepository contactTypeRepository; 
    @Test 
    public void testRepositoryNotNull() { 
     Assert.assertNotNull(contactTypeRepository); 
    } 

...} 

在觀看布維ld日誌,我可以看到每個測試的應用程序啓動。有沒有辦法讓BaseIntegrationTest只啓動一個,每個測試都使用該應用程序上下文和嵌入數據庫?

========

更新

我改變了我的JpaConfig這樣:

@Bean 
public DataSource dataSource() { 
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).setName("mydb") 
       .addScript("classpath:embeddedDatabase.sql").build(); 
} 

和我BaseIntegration現在是空的:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { JpaConfig.class }) 
public abstract class BaseItegration { 

} 

這裏是因爲錯誤而失敗的測試之一:

InvalidDataAccessResourceUsageException (Table "ADDRESSTYPEREF" not found; SQL statement:

@TransactionConfiguration(defaultRollback = true) 
@Transactional(propagation = Propagation.NESTED) 
public class TestSeedAddressTypesIT extends BaseItegration { 

    @Autowired 
    private AddressTypeRefRepository addressTypeRepository; 

    @Autowired 
    private SeedAddressTypes seedAddressTypes; 

    // hack because we can't do a BeforeClass with Autowired 
    private boolean seeded = false; 

    @Test 
    public void testRepositoryNotNull() { 
     Assert.assertNotNull(addressTypeRepository); 
    } 

    @Test 
    public void testPopulatedDB() { 
     if (!seeded) { 
      seedAddressTypes.seed(); 
      seeded = true; 
     } 
     List<AddressTypeRef> addressTypes = addressTypeRepository.findAll(); 
     Assert.assertEquals(5, addressTypes.size()); 

    } 
} 

然而,所有的集成測試似乎重新ApplicationContext的和嵌入式數據庫。雖然構建日誌不顯示正在創建的數據源,但我確實看到每個集成測試都創建一個新的log4j文件,45個測試需要15分鐘才能生成。

+0

AFAIK,不應該爲每個測試重新創建spring上下文。你如何運行測試?你確定你沒有配置測試運行器爲每個測試產生一個新的JVM嗎? –

+0

我正在使用「mvn clean verify」構建WAR文件。 – sonoerin

回答

2

看起來@BeforeClass表示任何使用@BeforeClass註釋的靜態方法在類中的任何測試方法之前運行。所以如果你有一個包含幾個類的測試套件,它的運行次數與測試類的數量相同。

爲什麼不在獨立的applicationContexts中初始化嵌入式數據庫和真正的數據庫並在測試中只添加嵌入式數據庫applicationContext?

例如(對不起,我不熟悉java配置樣式):

清單-1:嵌入式database.xml

<jdbc:embedded-database id="dataSource"> 
    <jdbc:script location="classpath:schema.sql"/> 
    <jdbc:script location="classpath:test-data.sql"/> 
</jdbc:embedded-database> 

清單-2:BaseItegration.java

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:your-application-without-a-real-database.xml", "classpath:"embedded-database.xml" }) 
public class BaseItegration { 


} 

然後用applicationContext啓動嵌入式數據庫(因此只有一次)。

另一個解決方案是使用Spring配置文件,您不必在單獨的xmls中分離數據庫。

清單1:你的應用程序上下文。XML

<bean profile="integrationTest"> 
    <jdbc:embedded-database id="dataSource"> 
     <jdbc:script location="classpath:schema.sql"/> 
     <jdbc:script location="classpath:test-data.sql"/> 
    </jdbc:embedded-database> 
<bean> 

<bean profile="production"> 
    //omitted 
</bean> 

上市-2:BaseItegration.java

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:your-application-context.xml" }) 
@ActiveProfiles("integrationTest") 
public class BaseItegration { 


} 

記住活動的產品在你的web.xml。

更新:

修改您的BaseIntegration作爲抽象類來解決沒有@Test方法問題。並且是在您的日誌中創建的數據源?

+0

我修改了BaseItegration,以便它不再創建嵌入式數據庫,還更改JpaConfig以創建嵌入式數據庫作爲數據源。但是現在我所有的集成測試都失敗了,因爲他們找不到數據庫。我更改了我的問題以反映這些更改 – sonoerin

+0

@sonoerin已更新,並且可以發佈您的BaseIntegration子類之一嗎? – Hippoom

+0

我用抽象基類和示例測試更新了我的文章。我沒有看到正在創建的數據源,但日誌文件是在每次測試時創建的,85次測試的總體構建時間爲15分鐘。 – sonoerin