2010-11-22 9 views
2


Ich versuche, meine DAO Schicht zu testen, in Trennung (die auf JPA gebaut wird). Im Komponententest verwende ich DbUnit, um die Datenbank und Spring Test zu füllen, um eine Instanz von ApplicationContext zu erhalten.Probleme mit DbUnit mit Frühlings-Testcontext

Wenn ich versuchte, den SpringJunit4ClassRuner zu verwenden, wurde der ApplicationContext injiziert, aber die Methode getDataSet() der DbUnit wurde nie aufgerufen.

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

Dann habe ich versucht die @RunWith Annotation, die die Probleme mit getDataSet() Methode entfernt zu entfernen. Aber jetzt bekomme ich keine ApplicationContext-Instanz mehr. Ich versuchte, die @TestExecutionListeners Annotation zu verwenden, die die DependencyInjectionTestExecutionListener standardmäßig konfiguriert werden soll, aber die AppContext noch nicht gespritzt bekommt.

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

Hat jemand irgendwelche Ideen? Ist es generell eine schlechte Idee, diese beiden Frameworks zu kombinieren?


EDIT: Hier ist der Rest der Quelle für die Testklasse:

@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; 
    } 
} 
+0

Der Grund, warum keine der DbTestCase Methoden aufgerufen ist undoubtebly die Tatsache, dass DbTestCase Klasse JUnit 3.8 API verwendet, und ich versuche, mit SpringJUnit4ClassRunner zulaufen. – prasopes

+0

Ich habe es geschafft DbUnit mit JUnit 4. Dieser Blog-Eintrag hat mir viel geholfen (Blick durch die Quelle für einige Schlüssel DbUnit Klassen verletzt entweder gar nicht) zu verwenden. http://ralf.schaeftlein.de/2009/01/05/dbunit-with-junit-4x-and-spring-for-testing-oracle-db-application/ – prasopes

Antwort

2

Ich habe diese beiden Frameworks zusammen ohne Probleme verwendet. Ich habe ein paar Dinge, die ein wenig anders als die Norm zu tun hatte, wenn es an die Arbeit:

@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. 

Ich habe Dinge zu tun, ein wenig mehr manuell, als ich möchte, aber das gleiche Szenario gilt, wenn Sie versuchen, die JUnit Parameterized Läufer mit Spring (in diesem Fall, dass Sie manuell die TextContext starten müssen) verwenden. Das Wichtigste ist, dass ich die Methode closeConnection() überschreibe und das Feld leer lasse. Dies überschreibt die Standardaktion des Schließens der dataSource-Verbindung nach jedem Test, die unnötige Zeit hinzufügen kann, da die Verbindung nach jedem Test erneut geöffnet werden muss.