2017-06-02 35 views
0

我試圖用spring和junit測試DAO方法,我看到一些在Internet上的做法是使用spring聲明式事務管理(@Transactional)進行業務操作時表示,測試完成後,Spring會讓測試方法回滾,從而達到測試的目的。單元測試,如何讓彈簧管理服務不污染數據庫

然後我按照這種方法添加了dao測試方法的操作,發現提交的事務,回滾不成功,數據庫我出來的測試數據。起初我以爲是春天沒有回滾,但在觀察控制檯後面打印信息發現有回滾信息,但爲什麼會失敗,不知道。我發現了一些相關的程序,但是我發現這並沒有解決我的問題。非常困擾,希望得到你的幫助!

以下是我的代碼和文件配置

  • DAOImpl的ADDUSER()方法

    @Override 
    public void addUser(User u) { 
        Session session = sessionFactory.openSession(); 
        Transaction tc = session.getTransaction(); 
        try { 
         tc.begin(); 
         session.save(u); 
         tc.commit(); 
        }catch(Exception e){ 
         tc.rollback(); 
         e.printStackTrace(); 
        } 
        return ; 
    } 
    
  • Daos.xml文件配置

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

測試類

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"/services.xml"}) 
@Transactional(transactionManager = "txManager") 
@Rollback(true) 
public class UserServiceImplTest { 
    @Autowired 
    UserDAO userDAO; 

    @Test 
    public void testAddUse(){ 
     User u = new User(); 
     u.setLevel(3); 
     u.setName("ab11"); 
     u.setPassword("hh"); 
     userDAO.addUser(u); 
     Assert.assertEquals(u.getName(), userDAO.getUserList().get(userDAO.getUserList().size()-1).getName()); 
    } 

一些控制檯打印信息

INFO: Using DataSource [[email protected]] of Hibernate SessionFactory for HibernateTransactionManager 
    JUNE 02, 2017 4:46:19 afternoon org.springframework.test.context.transaction.TransactionContext startTransaction 
INFO: Began transaction (1) for test context [[email protected] testClass = UserServiceImplTest, testInstance = [email protected], testMethod = [email protected], testException = [null], mergedContextConfiguration = [[email protected] testClass = UserServiceImplTest, locations = '{classpath:/services.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [[email protected]6634d]; rollback [true] 
    Fri Jun 02 16:46:19 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. 
    Hibernate: insert into user (name, password, level) values (?, ?, ?) 
    JUNE 02, 2017 4:46:19 afternoon org.springframework.test.context.transaction.TransactionContext endTransaction 
INFO: Rolled back transaction for test context [[email protected] testClass = UserServiceImplTest, testInstance = [email protected], testMethod = [email protected], testException = java.lang.RuntimeException, mergedContextConfiguration = [[email protected] testClass = UserServiceImplTest, locations = '{classpath:/services.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]. 
    JUNE 02, 2017 4:46:19 afternoon org.springframework.context.support.GenericApplicationContext doClose 
INFO: Closing [email protected]fc5af1: startup date [Fri Jun 02 16:46:13 CST 2017]; root of context hierarchy 
+0

對於記錄:當一個測試觸及**數據庫**,那麼不要稱之爲* unit *測試。 – GhostCat

+0

@GhostCat感謝您的建議。但我仍然不知道如何使Spring回滾。 –

+1

放心:如果我有答案,我會給它。這就是我來這裏的原因。大多數時候。:-) – GhostCat

回答

0

可悲的是,你在這裏混的一對概念。

您的生產代碼直接管理事務,而您的測試代碼使用AOP(面向方面​​編程)彈簧註釋。

由於您的生產代碼管理交易,所以測試代碼中的AOP註釋完全沒用:交易巫婆規則是生產代碼中的一個。

解決方案:在您的生產代碼中也使用AOP。讓健壯和經過充分測試的Spring事務機制來管理事務,並忘記自己管理事務。事情是這樣的:

@Override 
@Transactional(transactionManager = "txManager") 
public void addUser(User u) { 
    // only your bussiness logic here 
} 

更多信息:here (example)here(Spring manal)


This wikipedia article解釋相當好不同的軟件測試方法。你的屬於集成測試

+1

非常感謝,你的問題對我很有幫助。我找到了解決方案。因爲我沒有正確使用該事務,所以回滾失敗! 我開始意識到: 1.生產碼不應該是交易的管理; 2.應該使用getCurrentSession()並且不應該使用openSession()。 –

+0

不客氣。很高興你瞭解到了。我很難學會;) –