вторник, 18 ноября 2014 г.

Spring Tests + Jpa + DbUnitTest + JUnit


Подтягиваем зависимости
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${version.spring}</version>
</dependency>

<dependency>
    <groupId>com.github.springtestdbunit</groupId>
    <artifactId>spring-test-dbunit</artifactId>
    <version>1.1.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.dbunit</groupId>
    <artifactId>dbunit</artifactId>
    <version>2.4.9</version>
    <scope>test</scope>
<exclusions>
        <exclusion>
            <artifactId>junit</artifactId>
            <groupId>junit</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
</dependency>
Настраиваем контекст:
    <bean id="dbUnitDatabaseConnection"
          class="com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean">
        <property name="databaseConfig" ref="dbUnitDatabaseConfig"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="dbUnitDatabaseConfig" 
class="com.github.springtestdbunit.bean.DatabaseConfigBean">
        <property name="datatypeFactory">
            <bean class="org.dbunit.ext.postgresql.PostgresqlDataTypeFactory"/>
        </property>
        <property name="qualifiedTableNames" value="true"/>
    </bean>
    <bean id="dataSource" 
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
Вносим тестовые данные в xml-файл:
<dataset>
    <test.users id="1" email="test222@test.ru" username="Test222"/>
</dataset>
Пишем сам класс для тестирования:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring/application-context-test.xml")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
@DatabaseSetup(value = "/dbunit/userData.xml", type = DatabaseOperation.INSERT)
@DatabaseTearDown(value="/dbunit/userData.xml", type=DatabaseOperation.DELETE_ALL)
public class UserEntityRepositoryIT {

    @Autowired
    private co.brandly.repository.UserEntityRepository userEntityRepository;

    @Test
    public void shouldHaveNoObjectsAtStart() {

        List<UserEntity> results = (List<UserEntity>) userEntityRepository.findAll();
        assert (results.size() == 1);
    }
}
Можно добавить класс для замены произвольных значений в dataSet'e, например попробуем заменить "[now]" на сегодняшнюю дату. Наши данные в userData.xml:
<dataset>
    <test.users id="1"  username="Test222" created_at="[now]"/>
</dataset>
Класс, реализующий интерфейс DataSetLoader:
public class DateReplacementDataSetLoader implements DataSetLoader {

    private DataSetLoader delegate;

    public DateReplacementDataSetLoader() {
        this(new FlatXmlDataSetLoader());
    }

    public DateReplacementDataSetLoader(DataSetLoader delegate) {
        this.delegate = delegate;
    }

    public IDataSet loadDataSet(Class<?> testClass, String location) throws Exception {
        ReplacementDataSet replacementDataSet = new ReplacementDataSet(delegate.loadDataSet(testClass, location));
        replacementDataSet.addReplacementObject("[now]", DateTime.now());
        return replacementDataSet;
    }
}
Класс теста (не забываем аннотацию DbUnitConfiguration, с указанием выше созданного класса):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring/application-context-test.xml")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
@DatabaseSetup(value = "/dbunit/userData.xml", type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(value = "/dbunit/userData.xml", type = DatabaseOperation.DELETE_ALL)
@DbUnitConfiguration(dataSetLoader = DateReplacementDataSetLoader.class)
public class UserEntityRepositoryIT {

    @Autowired
    private co.brandly.repository.UserEntityRepository userEntityRepository;

    @Test
    public void shouldHaveNoObjectsAtStart() throws Exception {

        List<UserEntity> results = (List<UserEntity>) userEntityRepository.findAll();
        assert (results.size() == 3);
        assert (results.get(0).getCreatedAt()!=null);
    }
}