1

Not sure if I framed my question well enough. So, I am testing a DAO class using h2 in memory database. Here is my datasource-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="inMemoryDatabase" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="com.esb.h2.InMemoryDatabase.setUp" />
    <property name="arguments">
        <list>
            <value>db/schema.sql</value>
        </list>
    </property>
</bean>

<bean id="dataSource" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="inMemoryDatabase">
    <property name="staticMethod"><value>com.esb.h2.InMemoryDatabase.getDataSource</value></property>
</bean>

<bean id="namedParameterJdbcTemplate" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="inMemoryDatabase">
    <property name="staticMethod"><value>com.esb.h2.InMemoryDatabase.getJdbcTemplate</value></property>
</bean>
<bean id="catDao" class="com.esb.dao.impl.CatDAOImpl">
    <property name="template" ref="namedParameterJdbcTemplate" />
</bean>

Here is my unit-test.

public class CatalogDAOImplTest {

private static final String[] CONFIG_FILES = new String[] { "spring/datasource-test.xml"};
private CatDAO catDao;


@Before
public void setUp() throws Exception {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_FILES);
    catDao = (CatDAO)context.getBean("catDao");
 /*     context.destroy();
    context.close();*/
}

@After
public void tearDown() throws Exception {
    catDao = null;
}


@Test
public void testGetCat() {
    CatDTO cat = catDao.getCat("1234");
    assertEquals(null, cat);
}

@Test
public void testGetCatList1() {
    List<CatDTO> catList = catDao.getCatList();
    assertEquals(0, catList.size());
}


@Test
public void testSaveCatList() {
    CatDTO cat_save1 = new CatDTO(1, "2");
    CatDTO cat_save2 = new CatDTO(11, "22");
    List<CatDTO> catgList = new ArrayList<CatDTO>();
    catList.add(cat_save1);
    catList.add(cat_save2);
    catDao.saveCatList(catList);
    assertEquals("mismatch size: Cat List", 2, catDao.getCatList.size());
}


@Test
public void testGetCatList() {
    List<CatDTO> catList = catDao.getCatList();
    assertEquals(0, catList.size());
}

}

This test fails when the order of test execution is same as the order in which they are written but passes when both testGetCatList() and testGetCatList1() runs before testSaveCatList()

Looking at the console output, it does show me that these logs are generated for each one of junit-test, so @Before is working the way expected.

Refreshing 

org.springframework.context.support.ClassPathXmlApplicationContext@3f37bcb3: startup date [Fri Sep 11 13:20:01 EDT 2015]; root of context hierarchy
11/09/15 13:20:01,334 INFO  main org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/datasource-test.xml]
11/09/15 13:20:01,375 INFO  main org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/dao.xml]
11/09/15 13:20:01,413 INFO  main org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5bb9e289: defining beans [inMemoryDatabase,dataSource,namedParameterJdbcTemplate,catDao]; root of factory hierarchy
11/09/15 13:20:01,418 INFO  main org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory - Creating embedded database 'testdb'
11/09/15 13:20:01,419 INFO  main org.springframework.jdbc.datasource.init.ResourceDatabasePopulator - Executing SQL script from class path resource [db/schema.sql]
11/09/15 13:20:01,420 INFO  main org.springframework.jdbc.datasource.init.ResourceDatabasePopulator - Done executing SQL script from class path resource [db/schema.sql] in 1 ms.

I don't understand when its creating testdb again, why its referring to old db content.

Charu Khurana
  • 4,511
  • 8
  • 47
  • 81
  • Most simple guess would be, that all of your tests are referencing the SAME in-memory database, since the default for spring beans is SINGLETON, which means only one will be created and shared. You could try defining them as PROTOTYPE, but a more stable solution would perhaps be to ensure that every test does a rollback, which happens automatically if you open the transaction on the test method, using @Transactional. – Florian Schaetz Sep 11 '15 at 18:19
  • I am also thinking on same lines but what confuses me is that `@Before` is running for each method. There is a different context for all the test, so shouldn't it create another singleton bean each time and that does reflect from the logs – Charu Khurana Sep 11 '15 at 18:34
  • Hm, yes, you are right there, didn't think that through enough. Well, IF you get the same database all the time, it still should be enough to create the transaction in the test context, because spring then will rollback it automatically for you. But of course that doesn't answer the basic question... – Florian Schaetz Sep 11 '15 at 18:39
  • Perhaps a good idea would be to start debugging. Find out which objects are singletons/shared, if any. If they are not, the only thing left would be, that you only get only one database. I assume that the database does not modifiy the original file, does it? – Florian Schaetz Sep 11 '15 at 18:44
  • Added `@Transactional` on `testSaveCatList()` but still the same behavior – Charu Khurana Sep 11 '15 at 18:51
  • Sorry didn't get this ` I assume that the database does not modifiy the original file, does it?`??? – Charu Khurana Sep 11 '15 at 18:52
  • Ah, sorry, I assume that Spring simply does not notice the annotation since it has no control over the test class, as you create your context manually. Try adding `@RunWith(SpringJUnit4ClassRunner.class)` and `@ContextConfiguration(locations={...})` to let Spring manage your test and handle the Transactions for you (then you can autowired the dao, no need for manual context). See http://stackoverflow.com/questions/12626502/rollback-transaction-after-test . What I meant with the other idea was, that I assume that your database does not actually modify the db/schema.sql file. – Florian Schaetz Sep 11 '15 at 18:57

0 Answers0