2012-10-05 150 views
5

出於某種原因,@Value註解沒有被注入到我的課,我現在把它用作其他測試類的基。我是Spring的新手,我的Java知識並不是最好的。我相信對於有更多經驗的人來說,這一點會更加明顯,但我無法弄清楚這一點。@Value註釋文件

如果我註釋掉setDbProperties()方法,這些字段是填充的,但僅使用@Value註釋,我會在字段中獲得空值。

這裏是我的基礎測試類:

package com.blah; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.util.Properties; 

import org.dbunit.DBTestCase; 
import org.dbunit.PropertiesBasedJdbcDatabaseTester; 
import org.dbunit.dataset.IDataSet; 
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; 
import org.dbunit.operation.DatabaseOperation; 
import org.junit.After; 
import org.junit.Before; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.test.context.ActiveProfiles; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { 
     "classpath:/WEB-INF/application-context.xml", 
     "classpath:/WEB-INF/application-context-test.xml" }) 
@ActiveProfiles("test") 
public abstract class BaseDbTestCase extends DBTestCase { 

    @Value("${test.db.connection.url}") 
    private String connectionUrl; 

    @Value("${test.db.driver.class}") 
    private String driverClass; 

    @Value("${test.db.username}") 
    private String dbUserName; 

    @Value("${test.db.password}") 
    private String dbPassword; 

    @Value("${test.db.datasource.path}") 
    private String dataSource; 

    public BaseDbTestCase(String name) throws IOException { 

     super(name); 

     // setDbProperties(); 

     System.setProperty(
       PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, 
       driverClass); 
     System.setProperty(
       PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, 
       connectionUrl); 
     System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, 
       dbUserName); 
     System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, 
       dbPassword); 
    } 

    @After 
    public void after() throws Exception { 
     DatabaseOperation.DELETE_ALL.execute(getConnection(), getDataSet()); 
    } 

    @Override 
    protected IDataSet getDataSet() throws Exception { 
     return new FlatXmlDataSetBuilder() 
       .build(new FileInputStream(dataSource)); 
    } 

    private void setDbProperties() throws IOException, FileNotFoundException { 

     Properties properties = new Properties(); 

     properties.load(new FileInputStream(
       "src/main/java/resources/application.properties")); 

     connectionUrl = properties.getProperty("test.db.connection.url"); 
     driverClass = properties.getProperty("test.db.driver.class"); 
     dbUserName = properties.getProperty("test.db.username"); 
     dbPassword = properties.getProperty("test.db.password"); 
     dataSource = properties.getProperty("test.db.datasource.path"); 
    } 

    @Override 
    protected DatabaseOperation getSetUpOperation() throws Exception { 
     return DatabaseOperation.REFRESH; 
    } 

    @Override 
    protected DatabaseOperation getTearDownOperation() throws Exception { 
     return DatabaseOperation.NONE; 
    } 

    @Before 
    public void init() throws Exception { 
     DatabaseOperation.REFRESH.execute(getConnection(), getDataSet()); 
    } 

} 

正如你所看到的,其他春季(和非彈簧)的註解是在這個類的工作。

我有<context:property-placeholder location="classpath:/resources/application.properties" />在我的應用程序上下文。

另外,@Value註解在擴展BaseDbTestCase類的類中工作正常。

TIA

更新: 採取@六必居的建議,系統屬性的設置移動到init()方法(與@Before註釋)之後,我現在得到以下堆棧跟蹤。基於調試,它在拋出錯誤之前似乎沒有超過構造函數。

org.dbunit.assertion.DbAssertionFailedError: driverClass is null 
    at org.dbunit.assertion.DefaultFailureHandler$DefaultFailureFactory.createFailure(DefaultFailureHandler.java:265) 
    at org.dbunit.assertion.DefaultFailureHandler.createFailure(DefaultFailureHandler.java:110) 
    at org.dbunit.assertion.SimpleAssert.fail(SimpleAssert.java:90) 
    at org.dbunit.assertion.SimpleAssert.assertTrue(SimpleAssert.java:77) 
    at org.dbunit.assertion.SimpleAssert.assertNotNullNorEmpty(SimpleAssert.java:61) 
    at org.dbunit.JdbcDatabaseTester.<init>(JdbcDatabaseTester.java:103) 
    at org.dbunit.PropertiesBasedJdbcDatabaseTester.<init>(PropertiesBasedJdbcDatabaseTester.java:68) 
    at org.dbunit.DBTestCase.newDatabaseTester(DBTestCase.java:70) 
    at org.dbunit.DatabaseTestCase.getDatabaseTester(DatabaseTestCase.java:109) 
    at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:151) 
    at junit.framework.TestCase.runBare(TestCase.java:132) 
    at junit.framework.TestResult$1.protect(TestResult.java:110) 
    at junit.framework.TestResult.runProtected(TestResult.java:128) 
    at junit.framework.TestResult.run(TestResult.java:113) 
    at junit.framework.TestCase.run(TestCase.java:124) 
    at junit.framework.TestSuite.runTest(TestSuite.java:243) 
    at junit.framework.TestSuite.run(TestSuite.java:238) 
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
+0

我也有同樣的問題。你能找到解決方案嗎? –

回答

1

我想原因是因爲當你根據你的BaseDbTestCase在BaseDbTestCase的@ContextConfiguration派生出新的測試用例是不是真的在派生測試用例可見 - 在@ContextConfiguration必須是對你最後的測試案例。

更新:

上面我所投入是不正確的,我測試了一次,它看起來像@ContextConfiguration@RunWith即使在基類是充分,正確地注射在@Value領域的基礎類。

現在你遇到的問題是因爲你期望變量在構造函數中可用 - 它們不會,因爲@Value在實例創建後解析 - 所以在你的情況下,因爲你期待它在構造函數中出現它將會失敗。您應該可以設置屬性@Before Junit的註釋方法

+0

「@ContextConfiguration」的位置似乎並不重要。無論哪種方式,使用'@ Value'註解的字段都不會填充。 – Luke

+0

添加了更新後的答案 - 原因是您期望值在構造函數中反映,而@ Value在構建後解析。 –

+0

出於某種原因,在這種特殊情況下,系統屬性的設置必須在構造函數中發生,否則我永遠不會通過構造函數。相反,我得到了堆棧跟蹤,我更新了我的問題。有任何想法嗎? – Luke

0

有一個擴展BaseDbTestCase並將@ContextConfiguration放入具體類的具體類。讓你的其他測試類擴展這個具體的類。