2016-02-18 2 views
0

Я пытаюсь создать некоторую среду тестирования интеграции и столкнулся с проблемой, когда Test Context Framework не создает транзакционные прокси для моих компонентов. Мой код:@ContextConfiguration не создает прокси транзакции

JUnit класс: FileServiceImplTest

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextHierarchy({ 
     @ContextConfiguration(value = "file:src/main/webapp/WEB-INF/spring/applicationContext-db.xml"), 
     @ContextConfiguration(value = "file:src/main/webapp/WEB-INF/spring/applicationContext.xml") 
}) 
public class FileServiceImplTest { 

    @Autowired 
    private FileService fileService; 

    @Test 
    public void testSaveFolder() { 
     FolderDTO rootFolder = new FolderDTO(); 
     rootFolder.setName("ROOT"); 
     rootFolder.setParentId(null); 
     rootFolder.setIdPath("/"); 
     rootFolder.setPath("/"); 

     fileService.saveFile(rootFolder); 

     List<AbstractFileDTO> rootFiles = fileService.getRootFiles(); 

     assertEquals(1, rootFiles.size()); 

     AbstractFileDTO abstractFileDTO = rootFiles.get(0); 

     assertEquals(rootFolder, abstractFileDTO); 

    } 

} 

контекст Тест рамки работы впрыснуть в 'fileService' подал сам FileService боб, а не сделка прокси. Это причина исключения:

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 
    at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:132) 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:697) 
    at org.sbezgin.p2016.db.dao.impl.FileDAOImpl.getSession(FileDAOImpl.java:69) 
    at org.sbezgin.p2016.db.dao.impl.FileDAOImpl.saveOrUpdateFile(FileDAOImpl.java:33) 
    at org.sbezgin.p2016.services.file.impl.FileServiceImpl.saveFile(FileServiceImpl.java:41) 
    at org.sbezgin.p2016.services.file.impl.FileServiceImplTest.testSaveFolder(FileServiceImplTest.java:35) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) 

Когда я запускаю этот код под TOMCAT все работает нормально, проблема появляется только во время ходовых испытаний. Пожалуйста, помогите исправить это.

Остальной мой код: FileServiceImpl

@Transactional 
public class FileServiceImpl implements FileService { 
    private FileDAO fileDAO; 
    private BeanTransformer beanTransformer; 

    @Override 
    public AbstractFileDTO getFileByID(long fileID) { 
     return null; 
    } 

    @Override 
    public FolderDTO getFolder(long folderID) { 
     return null; 
    } 

    @Transactional(propagation = Propagation.REQUIRED) 
    @Override 
    public void saveFile(AbstractFileDTO file) { 
     Long id = file.getId(); 
     if (id == null) { 
      AbstractFile fileEntity = (AbstractFile) beanTransformer.transformDTOToEntity(file); 
      User user = new User(); 
      user.setId(1); 
      fileDAO.saveOrUpdateFile(user, fileEntity); 
     } 
    } 

    @Override 
    public void setPermission(long fileD, PermissionDTO perm) { 

    } 

    @Override 
    public void renameFile(long fileID, String newName) { 

    } 

    @Override 
    public void deleteFile(long fileID, boolean recursively) { 

    } 

    @Override 
    public List<AbstractFileDTO> getRootFiles() { 
     User user = new User(); 
     user.setId(1); 
     List<AbstractFile> rootFiles = fileDAO.getRootFiles(user); 
     List<AbstractFileDTO> abstractFileDTOs = new ArrayList<>(rootFiles.size()); 
     abstractFileDTOs.addAll(
       rootFiles.stream().map(
         rootFile -> (AbstractFileDTO) beanTransformer.transformEntityToDTO(rootFile) 
       ).collect(Collectors.toList()) 
     ); 
     return abstractFileDTOs; 
    } 

    @Override 
    public List<AbstractFileDTO> getChildren(long folderID) { 
     return null; 
    } 

    @Override 
    public List<AbstractFileDTO> getFilesByType(String javaType) { 
     return null; 
    } 


    public FileDAO getFileDAO() { 
     return fileDAO; 
    } 

    public void setFileDAO(FileDAO fileDAO) { 
     this.fileDAO = fileDAO; 
    } 

    public BeanTransformer getBeanTransformer() { 
     return beanTransformer; 
    } 

    public void setBeanTransformer(BeanTransformer beanTransformer) { 
     this.beanTransformer = beanTransformer; 
    } 
} 

FileDAOImpl.java

public class FileDAOImpl implements FileDAO { 

    private SessionFactory sessionFactory; 

    @Override 
    public AbstractFile getFileByID(User user, long fileID) { 
     return null; 
    } 

    @Override 
    public Folder getFolder(User user, long folderID) { 
     return null; 
    } 

    @Transactional(propagation = Propagation.REQUIRED) 
    @Override 
    public void saveOrUpdateFile(User user, AbstractFile file) { 
     Session session = getSession(); 
     file.setClassName(file.getClass().getCanonicalName()); 
     file.setOwnerID(user.getId()); 
     session.save(file); 
    } 

    @Override 
    public void saveOrUpdateFiles(User user, List<AbstractFile> files) { 

    } 

    @Override 
    public void deleteFile(User user, long fileID, boolean recursively) { 

    } 

    @Override 
    public List<AbstractFile> getRootFiles(User user) { 
     Session session = getSession(); 
     Query query = session.createQuery("from AbstractFile as file where file.ownerID = :ownerId and file.parentId is null "); 
     query.setParameter("ownerId", user.getId()); 
     List list = query.list(); 
     return list; 
    } 

    @Override 
    public List<AbstractFile> getChildren(User user, long folderID) { 
     return null; 
    } 

    @Override 
    public List<AbstractFile> getFilesByType(User user, String javaType) { 
     return null; 
    } 

    private Session getSession() { 
     return sessionFactory.getCurrentSession(); 
    } 

    public SessionFactory getSessionFactory() { 
     return sessionFactory; 
    } 

    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 
} 

applicationContext.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" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 

    <bean name="dozer" class="org.dozer.DozerBeanMapper" /> 

    <bean name="beanTransformer" class="org.sbezgin.p2016.services.impl.BeanTransformerImpl"> 
     <property name="dozerBeanMapper" ref="dozer"/> 
     <property name="beanMap"> 
      <map> 
       <entry key="org.sbezgin.p2016.db.dto.file.FolderDTO" value="org.sbezgin.p2016.db.entity.file.Folder"/> 
      </map> 
     </property> 
    </bean> 

    <!-- services --> 
    <bean name="fileService" class="org.sbezgin.p2016.services.file.impl.FileServiceImpl"> 
     <property name="fileDAO" ref="fileDAO" /> 
     <property name="beanTransformer" ref="beanTransformer"/> 
    </bean> 

    <!-- dao --> 
    <bean name="fileDAO" class="org.sbezgin.p2016.db.dao.impl.FileDAOImpl"> 
     <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 
</beans> 

ApplicationContext-db.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" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> 

    <context:property-placeholder location="WEB-INF/hibernate.properties" ignore-unresolvable="false"/> 

    <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.hibernate5.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="packagesToScan"> 
      <list> 
       <value>org.sbezgin.p2016.db.entity</value> 
      </list> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
       <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop> 
       <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop> 
       <prop key="hibernate.id.new_generator_mappings">${hibernate.id.new_generator_mappings}</prop> 
       <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager"/> 

</beans> 

hibernate.properties

jdbc.driverClassName = org.hsqldb.jdbcDriver 
    jdbc.url = jdbc:hsqldb:hsql://localhost:9001/xdb 
    jdbc.username = sa 
    jdbc.password = 
    hibernate.dialect = org.hibernate.dialect.HSQLDialect 
    hibernate.show_sql = true 
hibernate.format_sql = true 
hibernate.id.new_generator_mappings = false 
hibernate.hbm2ddl.auto = create-drop 

pom.xml

<dependencies> 
     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core</artifactId> 
      <version>5.0.7.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-context</artifactId> 
      <version>4.2.4.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-webmvc</artifactId> 
      <version>4.2.4.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-tx</artifactId> 
      <version>4.2.4.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-orm</artifactId> 
      <version>4.2.4.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>net.sf.dozer</groupId> 
      <artifactId>dozer</artifactId> 
      <version>5.5.1</version> 
     </dependency> 
     <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>5.1.38</version> 
     </dependency> 

     <dependency> 
      <groupId>javax.servlet</groupId> 
      <artifactId>javax.servlet-api</artifactId> 
      <version>3.0.1</version> 
      <scope>provided</scope> 
     </dependency> 
     <!-- TEST artifacts --> 
     <dependency> 
      <groupId>org.mockito</groupId> 
      <artifactId>mockito-all</artifactId> 
      <version>1.9.5</version> 
     </dependency> 
     <dependency> 
      <groupId>org.powermock</groupId> 
      <artifactId>powermock-module-junit4</artifactId> 
      <version>1.5</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.powermock</groupId> 
      <artifactId>powermock-api-mockito</artifactId> 
      <version>1.5</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.11</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>4.2.4.RELEASE</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.hsqldb</groupId> 
      <artifactId>hsqldb</artifactId> 
      <version>2.2.8</version> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 
    <build> 
     <finalName>p2016</finalName> 
     <plugins> 
      <plugin> 
       <!-- current version --> 
       <groupId>fr.avianey.mojo</groupId> 
       <artifactId>hsqldb-maven-plugin</artifactId> 
       <version>1.0.0</version> 

       <!-- 
        default value for in memory jdbc:hsqldb:hsql://localhost/xdb 
        override only values you want to change 
       --> 
       <configuration> 
        <driver>org.hsqldb.jdbcDriver</driver> 
        <address>localhost</address> 
        <port>9001</port> 
        <name>xdb</name> 
        <username>sa</username> 
        <password></password> 
        <validationQuery>SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS</validationQuery> 
       </configuration> 

       <!-- call start and stop --> 
       <executions> 
        <execution> 
         <id>start-hsqldb</id> 
         <phase>process-test-classes</phase> 
         <goals> 
          <goal>start</goal> 
         </goals> 
        </execution> 
        <execution> 
         <id>stop-hsqldb</id> 
         <phase>post-integration-test</phase> 
         <goals> 
          <goal>stop</goal> 
         </goals> 
        </execution> 
       </executions> 
      </plugin> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>3.3</version> 
       <configuration> 
        <source>1.8</source> 
        <target>1.8</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 
+0

Вы пытались добавить '@ Transactional' на свой' FileServiceImplTest '? –

ответ

0

на основе Spring Framework documentation-х:

TestContext В рамках сделки управляются TransactionalTestExecutionListener, который настроен по умолчанию, , даже если вы явно не объявите @TestExecutionListeners на свой тестовый класс . Однако для обеспечения поддержки транзакций вы должны установить PlatformTransactionManager компонент ApplicationContext , который загружается через @ContextConfiguration семантика. Кроме того, вы должны объявить аннотацию Spring @Transactional на уровне класса или метода для ваших тестов .

Вы сделали определить PlatformTransactionManager в вашем applicationContext-db.xml но не добавлял @Transactional на вашем FileServiceImplTest классе или testSaveFolder метода. Добавьте @Transactional на свой тестовый класс или методы.

+0

Это решение меня не устраивает, потому что я хочу иметь ту же среду, что и в веб-контейнере. Если я добавлю _ @ Transactional_ для проверки метода, это означает, что фиксация в БД будет выполняться только при завершении выполнения тестового метода. Я хочу, чтобы spring make совершает после выполнения каждый транзакционный метод, как он был объявлен в FileServiceImpl. – SergiiB

+0

Затем используйте 'TestTransactions' в сочетании с' @ Transactional', чтобы передать текущую транзакцию после каждого вызова службы. Без добавления '@ Transactional' у вас не было бы транзакций в вашем TestContext. –

+0

Да, я сделаю это. Большое спасибо ! – SergiiB

0

Я обнаружил, что мне пришлось добавить @EnableTransactionManagement к моей конфигурации. До этого Spring не запускал SpringTransactionAnnotationParser и добавлял методы транзакций proxy к моему bean-компоненту. Я только добавил его к одному тесту, потому что он будет выполнять все тесты, которые будут выполняться по-другому, чем они хотят (для управления транзакциями и автоматического возврата их назад)

Смежные вопросы