Pregunta


Estoy tratando de probar mi capa DAO (que se basa en JPA) en la separación. En la prueba unitaria, estoy usando DbUnit para poblar la base de datos y pruebas de la primavera para obtener una instancia de Application Context.

Cuando traté de utilizar el SpringJunit4ClassRuner, el Application Context consiguió inyecta, pero del DbUnit getDataSet () método nunca se llama.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/testdao.xml")
public class SimpleJPATest extends DBTestCase implements ApplicationContextAware {
    ...

Luego probé para eliminar la anotación @RunWith, que elimina los problemas con el método () getDataSet. Pero ahora ya no recibo instancia Application Context inyectado. He intentado utilizar la anotación @TestExecutionListeners, que se supone para configurar el DependencyInjectionTestExecutionListener por defecto, pero el AppContext todavía no consigue inyectado.

@TestExecutionListeners
@ContextConfiguration(locations = "/testdao.xml")
public class SimpleJPATest extends DBTestCase implements ApplicationContextAware {
    ...

¿Alguien tiene alguna idea? Es generalmente una mala idea de combinar estos dos marcos?


Edit: aquí está el resto de la fuente de la clase de prueba:

@TestExecutionListeners
@ContextConfiguration(locations = "/testdao.xml")
public class SimpleJPATest extends DBTestCase implements ApplicationContextAware {

    static final String TEST_DB_PROPS_FILE = "testDb.properties";
    static final String DATASET_FILE = "testDataSet.xml";
    static Logger logger = Logger.getLogger( SimpleJPATest.class );
    private ApplicationContext ctx;

    public SimpleJPATest() throws Exception {
        super();
        setDBUnitSystemProperties(loadDBProperties());
    }

    @Test
    public void testSimple() {
        EntityManagerFactory emf = ctx.getBean("entityManagerFactory", EntityManagerFactory.class);
        EntityManager em = emf.createEntityManager();
        GenericDAO<Club> clubDAO = new JpaGenericDAO<Club>(ClubEntity.class, "ClubEntity", em);
        em.getTransaction().begin();
        Collection<Club> allClubs = clubDAO.findAll();
        em.getTransaction().commit();
        assertEquals(1, allClubs.size());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         this.ctx = applicationContext;
    }

    private void setDBUnitSystemProperties(Properties props) {
        System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS,
                props.getProperty("db.driver"));
        System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL,
                props.getProperty("db.url"));
        System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME,
                props.getProperty("db.username"));
        System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD,
                props.getProperty("db.password"));

    }

    private Properties loadDBProperties() throws Exception {
        URL propsFile = ClassLoader.getSystemResource(TEST_DB_PROPS_FILE);
        assert (propsFile != null);
        Properties props = new Properties();
        props.load(propsFile.openStream());
        return props;
    }

    @Override
    protected void setUpDatabaseConfig(DatabaseConfig config) {
        config.setProperty( DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
            new HsqldbDataTypeFactory() );
    }

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

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

    @Override
    protected IDataSet getDataSet() throws Exception {
        logger.debug("in getDataSet");
        URL dataSet = ClassLoader.getSystemResource(DATASET_FILE);
        assert (dataSet != null);
        FlatXmlDataSet result = new FlatXmlDataSetBuilder().build(dataSet);
        return result;
    }
}
¿Fue útil?

Solución

He usado estos dos marcos juntos sin ningún problema. He tenido que hacer algunas cosas un poco diferente de la norma, aunque para conseguir que funcione:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class })
public class MyDaoTest extends DBTestCase {

@Autowired
private MyDao myDao;

/**
 * This is the underlying BasicDataSource used by Dao. If The Dao is using a
 * support class from Spring (i.e. HibernateDaoSupport) this is the
 * BasicDataSource that is used by Spring.
 */
@Autowired
private BasicDataSource dataSource;

/**
 * DBUnit specific object to provide configuration to to properly state the
 * underlying database
 */
private IDatabaseTester databaseTester;

/**
 * Prepare the test instance by handling the Spring annotations and updating
 * the database to the stale state.
 * 
 * @throws java.lang.Exception
 */
@Before
public void setUp() throws Exception {
    databaseTester = new DataSourceDatabaseTester(dataSource);
    databaseTester.setDataSet(this.getDataSet());
    databaseTester.setSetUpOperation(this.getSetUpOperation());
    databaseTester.onSetup();
}

/**
 * Perform any required database clean up after the test runs to ensure the
 * stale state has not been dirtied for the next test.
 * 
 * @throws java.lang.Exception
 */
@After
public void tearDown() throws Exception {
    databaseTester.setTearDownOperation(this.getTearDownOperation());
    databaseTester.onTearDown();
}

/**
 * Retrieve the DataSet to be used from Xml file. This Xml file should be
 * located on the classpath.
 */
@Override
protected IDataSet getDataSet() throws Exception {
    final FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
    builder.setColumnSensing(true);
    return builder.build(this.getClass().getClassLoader()
            .getResourceAsStream("data.xml"));
}

/**
 * On setUp() refresh the database updating the data to the data in the
 * stale state. Cannot currently use CLEAN_INSERT due to foreign key
 * constraints.
 */
@Override
protected DatabaseOperation getSetUpOperation() {
    return DatabaseOperation.CLEAN_INSERT;
}

/**
 * On tearDown() truncate the table bringing it back to the state it was in
 * before the tests started.
 */
@Override
protected DatabaseOperation getTearDownOperation() {
    return DatabaseOperation.TRUNCATE_TABLE;
}

/**
 * Overridden to disable the closing of the connection for every test.
 */
@Override
protected void closeConnection(IDatabaseConnection conn) {
    // Empty body on purpose.
}
// Continue TestClass here with test methods.

He tenido que hacer las cosas un poco más manual de lo que quisiera, pero el mismo escenario se aplica si se intenta utilizar el corredor JUnit con parámetros con la primavera (en ese caso hay que iniciar el TextContext manualmente). Lo más importante a destacar es que puedo reemplazar el método closeConnection () y dejarla en blanco. Esto anula la acción por defecto del cierre de la conexión dataSource después de cada prueba que se puede añadir el tiempo innecesario, ya que la conexión tendrá que ser abierto de nuevo después de cada prueba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top