Spring下的Unit Test Notes 2nd

來源:互聯網
上載者:User

     作者:江南白衣  

     注重實效的TDD的確能加快,而不是拖慢開發的進度(片面的追求覆蓋率的全面UnitTest不在此列)
      一,可以實現真正分層開發。
      二,不需要依賴和頻繁重啟Web Container。
      三,手工測試總不免改動資料庫,如何把資料庫恢複到測試前的狀態是件傷腦筋的事情。而Unit Test可以使用自動Rollback機制,巧妙的解決了這件事情。

      Spring 下的Unit Test主要關注三個方面:
       1. bean的依賴注入
       2. 事務控制,Open Session in Test 及預設復原
       3. 脫離WebContainer對控制層的測試
      

   1.bean的依賴注入 
  能不依靠WebContainer來完成ApplicationContext的建立與POJO的依賴注入一向是Spring的得意之處。

String[] paths = { "classpath:applicationContext*.xml" };
ApplicationContext ctx =new ClassPathXmlApplicationContext(paths);
UserDAO dao = (UserDAO) ctx.getBean("userDAO");

    如果你連這也覺得麻煩,那麼只要你的testCase繼承於Spring-mock.jar裡的AbstractDependencyInjectionSpringContextTests,實現public String[] getConfigLocations()函數, 並顯式寫一些需要注入的變數的setter函數。
    註:因為是AutoWire的,變數名必須等於Spring  context檔案裡bean的id。

2.Open Session in Test 及自動Rollback
     又是來自Spring這個神奇國度的東西, 你可以讓testCase繼承於AbstractTransactionalDataSourceSpringContextTests,就可以做到Open Session in Test ,解決Hibernate的lazy-load問題;而且接管原來的DAO裡的事務控制定義,通過setDefaultRollback(boolean)方法控制最後復原還是提交,如果預設為復原,則測試產生資料變動不會影響資料庫內資料。
 
    如果不能繼承於這個基類,可以自己簡單編寫,代碼是這樣的:

   protected PlatformTransactionManager transactionManager;
   protected TransactionStatus transactionStatus;
   protected boolean defaultRollback = true;
   public void setUp()
   {
        transactionManager = (PlatformTransactionManager) ctx.getBean("transactionManager");
        transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
   }
   public void tearDown()
   {
        if (defaultRollback)
            transactionManager.rollback(this.transactionStatus);
        else
           transactionManager.commit(this.transactionStatus);
    }

  (注,hibernate太奸詐了,如果全部預設復原,只會在session裡幹活,一點不寫資料庫,達不到完全的測試效果。)

BTW.AbstractTransactionalDataSourceSpringContextTests 還通過注入的DataSource建立了一個JDBCTemplate 對象,可以跑SQL幫忙核對Hibernate的結果,但要注意兩者的事務。

3.Controller層的Unit Test

controller層靠Spring提供的MockHttpServletRequest和Response來類比真實的servlet環境,並且spring 2.0了加了一個AbstractModelAndViewTests,提供一些檢測傳回值的utils函數。

    protected XmlWebApplicationContext ctx;
    protected MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
    protected MockHttpServletResponse response = new MockHttpServletResponse();
    protected Controller controller = null;
    protected ModelAndView mv = null;
   public void setUp()
   {
        String[] paths = {"applicationContext*.xml","myappfuse-servlet.xml"};
        ctx = new XmlWebApplicationContext();
        ctx.setConfigLocations(paths);
        ctx.setServletContext(new MockServletContext(""));        ctx.refresh();
        controller = (CustomerController) ctx.getBean("customerController");
        //再加上前文的事務控制的代碼
   }
    public void testCustomerList() throws Exception
    {
        request.setRequestURI("/customer.do");
        request.addParameter("action", "listView");
        mv = controller.handleRequest(request, response);
        assertModelAttributeAvailable(mv, "customers");
    }

  
4.進一步簡化
一來這兩個基類的名字都太長了。
二來有一些公用的context檔案的定義。

所以可以再抽象了幾個基類,分別是DAOTestCase,ControllerTestCase。

5. EasyMock
   MockObject是一樣徹底分層開發的好東西,而且使用上沒什麼難度。而且已不再存在只支援介面不支援Class的限制。
  

//設定BookManager MockObject
        bookManagerMockControl = MockClassControl.createControl(BookManager.class);
        bookManagerMock = (BookManager) bookManagerMockControl.getMock();
        controller.setBookManager(bookManagerMock);
        
//錄製getAllBook()和getCategorys方法的期望值
        bookManagerMock.getAllBook();
        bookManagerMockControl.setReturnValue(new ArrayList());
        bookManagerMockControl.replay();
         
//執行操作
        mv = controller.handleRequest(request, response);
//驗證結果          
        assertModelAttributeAvailable(mv, "books");

   Easy Mock VS JMock:

    JMock 要求TestCase繼承於MockObjectTestCase太霸道了。妨礙了我繼承於Spring2.0的ModelAndViewTestCase和使用MockDao,RealDao並行的繼承體系。因此採用沒那麼霸道的easyMock。

   另外,easyMock的指令碼錄製雖不如jmock那麼優美,但勝在簡短易讀。jmock那句太長了 。

6. 顯示層測試
還有,顯示層至今沒有什麼好的UnitTest方法,無論是不成才的httpUnit們還是笨重的GUI test工具。Appfuse一直用的那個ThoughtWork那個Selenium和J3Unit的效果不知如何, 其中J3Unit號稱支援prototype。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.