【问题标题】:@Value annotations in base test class not injecting values from properties file基测试类中的@Value 注释不从属性文件中注入值
【发布时间】:2012-09-26 20:22:33
【问题描述】:

由于某种原因,@Value 注释没有被注入到我用作其他测试类的基础的类中。我是 Spring 新手,我对 Java 的了解还不是最好的。我相信这对于有更多经验的人来说会更明显,但我无法弄清楚。

如果我注释掉 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());
    }

}

如您所见,其他 Spring(和非 Spring)注释也在这个类中工作。

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

此外,@Value 注释在扩展 BaseDbTestCase 类的类中也能正常工作。

TIA

更新: 在接受@Biju 的建议将系统属性的设置移动到 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)

【问题讨论】:

  • 我也有同样的问题。你能找到解决办法吗?

标签: java spring spring-annotations


【解决方案1】:

有一个扩展 BaseDbTestCase 的具体类并将 @ContextConfiguration 放在具体类中。让你的其他测试类扩展这个具体的类。

【讨论】:

    【解决方案2】:

    我认为的原因是因为当您基于 BaseDbTestCase 派生新的测试用例时,BaseDbTestCase 中的 @ContextConfiguration 在派生的测试用例中并不真正可见 - @ContextConfiguration 必须在您的最终测试中案例。

    更新:

    我上面所说的不正确,我测试过一次,看起来即使在基类中 @ContextConfiguration@RunWith 也足够了,它正确地注入了基类中的 @Value 字段。

    现在您遇到的问题是因为您希望变量在构造函数中可用 - 它们不会,因为 @Value 在创建实例后被解析 - 所以在你的情况下,因为你期待它出现在构造函数中它将失败。您应该能够在 Junit 的 @Before 注释方法中设置属性

    【讨论】:

    • @ContextConfiguration 在哪里似乎并不重要。无论哪种方式,我用 @Value 注释的字段都不会被填充。
    • 添加了一个更新的答案 - 原因是您希望该值反映在构造函数中,而 @Value 在构造后得到解决。
    • 出于某种原因,在这种特殊情况下,系统属性的设置必须在构造函数中进行,否则我永远无法通过构造函数。相反,我得到了更新问题的堆栈跟踪。有什么想法吗?
    • 能否请您也显示您的 JdbcDatabaseTester 类,您可能仍在访问一些尚未根据 JdbcDatabaseTester 中的 @Value 填充的变量
    • 我使用的JdbcDatabaseTester 是dbunit 附带的,还有DBTestCase 类。在此处查看PropertiesBasedJdbcDatabaseTester 类...dbunit.org/apidocs/org/dbunit/…
    猜你喜欢
    • 2011-11-17
    • 2019-09-01
    • 1970-01-01
    • 2022-06-22
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多