2012-10-05 15 views
5

Por alguna razón, las anotaciones @Value no se están inyectando en mi clase que estoy utilizando como base para otras clases de prueba. Soy nuevo en Spring y mi conocimiento de Java no es el mejor hasta ahora. Estoy seguro de que esto será mucho más obvio para alguien con más experiencia, pero no puedo resolverlo.@Anotaciones de valor en la clase de prueba base que no inyectan valores desde el archivo de propiedades

Si comento el método setDbProperties(), los campos se rellenan, pero con las anotaciones @Value solo, obtengo valores nulos en los campos.

Aquí es mi base de clase de prueba:

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()); 
    } 

} 

Como se puede ver, otra primavera (y no de la primavera) anotaciones están trabajando en esta clase.

Tengo <context:property-placeholder location="classpath:/resources/application.properties" /> en el contexto de mi aplicación.

Además, las anotaciones @Value funcionan bien en las clases que amplían la clase BaseDbTestCase.

TIA

Actualización: @ Después de tomar la sugerencia de Biju para mover el ajuste de las propiedades del sistema para el método init() (anotado con @Before), ahora estoy recibiendo el siguiente seguimiento de la pila. En función de la depuración, parece que no pasa el constructor antes de lanzar el error.

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

Tengo el mismo problema. ¿Podrías encontrar una solución? –

Respuesta

1

La razón creo que es debido al derivar un nuevo caso de prueba en función de su BaseDbTestCase la @ContextConfiguration en el BaseDbTestCase no es realmente visible en el caso de prueba derivada - la @ContextConfiguration tiene que estar en su caso de la prueba final.

Actualización:

Lo que he puesto arriba no es correcta, he probado una vez y parece que la @ContextConfiguration y @RunWith incluso en la clase base es suficiente y se inyecta correctamente en los @Value campos en la base clase.

Ahora el problema que está teniendo es que espera que las variables estén disponibles en el constructor; no lo serán, porque el @Value se resuelve DESPUÉS de que se cree la instancia, por lo que en su caso ya que lo está esperando estar presente en el constructor fallará. En su lugar, debería poder establecer las propiedades en @Before método anotado de Junit

+0

No parece importar dónde está el '@ ContextConfiguration'. De cualquier forma, mis campos anotados con '@ Value' no se llenan. – Luke

+0

Se agregó una respuesta actualizada: el motivo es que se espera que el valor se refleje en el constructor, mientras que '@ Value 'se resuelve después de la construcción. –

+0

Por alguna razón, en este caso particular, la configuración de las propiedades del sistema tiene que ocurrir en el constructor, de lo contrario, nunca pasar el constructor. En cambio, obtengo el seguimiento de la pila con el que actualicé mi pregunta. ¿Algunas ideas? – Luke

0

Tener una clase concreta que amplíe BaseDbTestCase y poner @ContextConfiguration en la clase concreta. Haga que sus otras clases de prueba amplíen esta clase concreta.

Cuestiones relacionadas