Как правильно выполнить интеграционное тестирование с помощью Hibernate 3 Spring 3.0.5 с помощью Spring Transaction Management (проект Maven) - PullRequest
0 голосов
/ 14 марта 2011

Я считаю, что этот вопрос задают снова и снова. Но я думаю, что здесь есть кое-что, что мне нужно понять раз и навсегда.

Я должен признать, что я очень плохо разбираюсь в том, как работает весеннее управление транзакциями, но я думал, что до сих пор понял, что означает интеграционный тест, где я полностью запутался.

вот как я пишу свой интеграционный тест (я предпочитаю интеграционный тест модульному тесту, когда прихожу тестировать уровень данных приложения, возможно, плохая привычка)

Я автоматически связываю объекты, добавляю их свойства в setup() и сохраняю их там для последующего использования, например, с такими методами, как getUser() или findUser/findAll(), а затем удаляю все из них в демонтаж. Я думаю, это работало раньше, когда я сам открывал и закрывал транзакцию.

Я решил попробовать аннотацию транзакции пружинного управления транзакциями.

Задача 1
когда я не добавляю пользователя модели в контекст, тест не проходит, потому что я считаю, что компонент для сканирования не работает: это ошибка

Не найден соответствующий бин типа [com.myproject.perso.admintest.model.User] для зависимости: ожидается, что по крайней мере 1 бин будет квалифицирован как кандидат для автоматической передачи для этой зависимости. Аннотации зависимостей: {@ Org.springframework.beans.factory.annotation.Autowired (обязательно = истина)}

тогда я должен раскомментировать его, то же самое для дао

задача 2

когда есть только один тест (testGetUser) и у меня есть только createUser(user1) в setup и delete(user1) в teardown. тест успешен. Даже с тем же самым конфигом в настройке и разборке, но на этот раз с testFindUser он все еще успешен с данными в базе данных и затем удален с разборкой ок. но как только я раскомментирую createUser (user2) в настройке и delete (user2) в демонтаже в дополнение к use1 create и delete, он выдаст

не удалось вставить: [com.myproject.perso.admintest.model.User]; SQL [вставить в значения пользователей (электронная почта, пароль, имя пользователя) (?,?,?)]; ограничение [ноль]; вложенным исключением является org.hibernate.exception.ConstraintViolationException:

Я понимаю, что это связано с тем, что сеанс не был сброшен (хотя я не очень хорошо его понимаю), читая посты других, но мой вопрос: когда приходит весеннее преобразование?

Вопросы
1 что-то не так с моим тестом?
2 , если я хочу сохранить свой подход, создав POJO в тесте, в отличие от использования DBUnit, например, для приборов, как мне создать этот тест.
3 что тогда делает управление весенними транзакциями во всем этом. спасибо

вот мои коды

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:WEB-INF/testadmin-webapp-config.xml"})
 public class UserDAOImplTest {


private UserDAO userDao;
@Autowired
public void setDao(UserDAO userDao){
   this.userDao = userDao;
}

@Autowired
User user1;

@Autowired
User user2;

public UserDAOImplTest() {
}

@Before
public void setUp() {

    user1.setEmail("user1@somemail.com");
    user1.setPassword("mypass");
    user1.setUsername("user1");

    user2.setEmail("user2@somemail.com");
    user2.setPassword("password");
    user2.setUsername("user2");

    userDao.createUser(user1);
    userDao.createUser(user2);
}

@After
public void tearDown() {
    userDao.delete(user1);
    userDao.delete(user2);
}



/**
 * Test of getUser method, of class UserDAOImpl.
 */
@Test
public void testGetUser() {
    System.out.println("getUser test");

    User expResult = user1;
    User result = userDao.getUser(user1.getId());

    Assert.assertEquals(expResult.getId(), result.getId());
    Assert.assertEquals(expResult.getEmail(), result.getEmail());


    }

  @Test
  public void testFindUser() {
    System.out.println("findUser");
    Assert.assertTrue(true);

  }
}

мой интерфейс DAO выглядит так

public interface UserDAO {

User getUser(Long userId);
User findUser(String name);
List<User> getAllUsers();
void createUser(User user);
void delete(User user);
void updateUser(User user);

}

это реализация выглядит так:

@Repository("UserDAO")
@Transactional
public class UserDAOImpl implements UserDAO {

HibernateTemplate hibernateTemplate;

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
    this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}

@Override
public User getUser(Long userId) {
   return hibernateTemplate.get(User.class, userId);
}

@Override
public User findUser(String username) {
   List found=  hibernateTemplate.find("from User u where u.username= ?", username);
   return (found.size() == 1) ? (User) found.get(0) : new User();
}

//......

@Override
@Transactional
public void createUser(User user) {
     hibernateTemplate.save(user);
}

@Override
@Transactional(readOnly=false)
public void delete(User user) {
    hibernateTemplate.delete(user);
}

// .....

my User POJO is like so

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long Id;
@Column(name="username" ,unique=true)
private String username;
@Column(name="password")
private String password;
@Column(name="email", unique=true)
private String email;

вот мой тестовый файл контекста

<!-- for i left out some part in order to be concise  -->
<context:annotation-config />
<context:component-scan base-package="com.myproject.perso.abmintest" />
<bean id="datasource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
 </bean>
 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
    <property name="dataSource" ref="datasource"  />
    <property name="packagesToScan" value="com.myproject.perso.admintest.model" />
    <property name="hibernateProperties" >
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl}</prop>
        </props>
    </property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Model Section-->
<!--<bean id="user" class="com.myproject.admintest.model.User" />-->

<!-- Model Section End-->
<!--DAO-->
<!--<bean id="userDao" class="com.myproject.admintest.dao.UserDAOImpl" />-->

<!--DAO end -->

вот мой помп

org.springframework (most of spring stuff including spring-asm)3.0.5.RELEASE
org.hibernate:hibernate-core 3.6.1.Final
org.hibernate:hibernate-cglig-repack 2.1_3
log4j:log4j1.2.14
org.slf4j:slf4j-log4j12 1.5.2
junit:junit 4.5
commons-collections:commons-collections 3.2.1
jboss:javassist 3.7.ga 
commons-logging:commons-logging 1.1.1

полный помп можно найти здесь

Ответы [ 2 ]

2 голосов
/ 03 апреля 2011

просто сделайте это просто приятель

@Autowired
private UserDAO userDao;

private User user1;

private User user2;

@Before
public void setUp() {
    user1 = new User();
    user1.setEmail("user1@somemail.com");
    user1.setPassword("mypass");
    user1.setUsername("user1");

    user2 = new User();
    user2.setEmail("user2@somemail.com");
    user2.setPassword("password");
    user2.setUsername("user2");
}

Было бы лучше, если бы создать пользовательский метод тестирования

@Test
public void testGetUser() {
    userDao.create(user1);

    User expResult = user1;
    User result = userDao.getUser(user1.getId());

    Assert.assertEquals(expResult.getId(), result.getId());
    Assert.assertEquals(expResult.getEmail(), result.getEmail());


}

Вы можете добавить @TransactionConfiguration для отката транзакции, например, Создать обновлениеОперация удаления.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:WEB-INF/testadmin-webapp-config.xml"})
@TransactionConfiguration(defaultRollback=true)
1 голос
/ 23 марта 2011

Не связывайте автоматически создаваемые объекты пользователя в методе настройки.

Если вы добавите аннотацию @Transactional в класс теста - Spring запустит транзакцию перед запуском теста (и метод установки) - запустите тест как часть транзакции, а затем откатите транзакцию.Таким образом, вам не нужно писать код в методе tearDown для явного удаления объектов (отмена действий, сделанных в настройке).

Вам придется вызывать flush / clear в сеансе - получая ссылкув SessionFactory, введенный в тест для принудительного запуска запросов и повторного извлечения объекта из базы данных.

...