2011-07-08 32 views
1

我正在爲使用JUnit的Spring Framework 2.5編寫單元測試。更具體地說,我使用MockHttpServletRequest來測試我的控制器。我遇到了一個問題,測試一個特定的場景。如何讓JUnit模擬打開多個選項卡/窗口,但只打開一個會話

一個應用程序正在編輯對象,堅持Hibernate。該對象的工作是這樣的:

Class Workflow { 
    ... various properties and methods 
    Long workflowId; // primary key for this object 
    Long subclassId; // foreign key to another class 
    String subclassType; // what kind of other class? 
} 

Class Request { 
    .. various other properties and methods 
    Long subclassId; // primary key for this object 
    Long workflowId; // foreign key to Workflow 
} 

工作也始終是連接到一個,而且只有一個,請求和要求總是附屬於一個,只有一個工作流程。但是,有多個工作流可以鏈接到的對象/表,因此子類必須跟蹤其他要查看的表。因此,這有點像請求繼承/實現工作流,但數據庫將它們存儲在單獨的表,所以Java被實現爲單獨的類。

我沒有寫這個爛攤子。我維護它。它有廣泛的用途,有幾個不同的應用程序和子類型,所以我可以做多少「清理」是有限制的。

有問題的Web應用程序將工作流對象放入HttpSession中,但編輯表單中的請求。當有人打開多個窗口/選項卡,並在每個窗口中使用不同的請求時,最後一個打開的工作流對象將覆蓋任何先前打開的對象(會話連接到Cookie,只有一組Cookie用於該域,由網頁瀏覽器中的所有窗口)。如果他們提交了第一個請求的表單,則最後一個(從HttpSession中取出)的Workflow對象被寫入提交的請求(不是正確的),從而破壞數據庫中的數據。

我們結束了有多個工作流連接到它們的請求,以及沒有工作流連接到它們的請求。

顯而易見的修復方法是重寫應用程序,以免它將工作流存儲在HttpSession中。 workflowId是請求中的一個字段;我們通過隱藏的領域堅持到形式。是的,我們更頻繁地訪問數據庫,但我們沒有交叉連接我們的記錄。

就是這樣的情況。現在,問題是:您如何在JUnit中對此進行建模?那麼,未來沒有人會再次遇到這種情況呢?

我們使用MockHttpServletRequest,插入表單值並使用AnnotationMethodHandlerAdapter和Controller對象提交它們。舉個例子:

MockHttpServletRequest request = new MockHttpServletRequest(); 
    MockHttpServletResponse response = new MockHttpServletResponse(); 
    AnnotationMethodHandlerAdapter handler = new AnnotationMethodHandlerAdaptor(); 
    RequestFormController controller = new RequestFormController(); 

    request.setMethod("GET"); 
    request.setRequestURI("/EditRequest.do"); // handled by the RequestFormController 

    request.setParameter("wfId", Long.toString(wfid)); // wfId is the workflow ID of a valid Workflow with an attached Request 
    ModelAndView mv = handler.handle(request, response, controller); 

    request.setParameter("wfId", mv.getModel().get("wfId"); 
    request.setParameter("requestText", "blah blah blah"); 

    request.setMethod("POST"); 
    request.setRequestURI("/UpdateRequest.do"); // handled by the RequestFormController 
    mv = handler.handle(request, response, controller); 

這是非常簡單的,Spring/JUnit的東西。問題是,要在兩個不同的選項卡/窗口中打開某些內容,必須有兩個不同的請求,每個請求都有自己的HttpSession。然而,使用網絡瀏覽器,這兩種不同請求共享相同的cookie,這意味着它們共享相同的會話信息。你如何讓JUnit建模?

我可以將cookie從一個複製到另一個,但似乎沒有暴露出錯誤。 MockHttpServletRequest仍然保持HttpSession信息分離。我很難將HttpSession屬性從一個複製到另一個。儘管我已經這麼做了,但我似乎也無法讓這個錯誤暴露出來。

有什麼建議嗎?這是一個非常現實的問題,我們正在做的MockHttpServletRequest和所有其他與JUnit相關的事情並不準確地模擬Tomcat和Web瀏覽器的真實世界。

和平。

回答

0

在編寫測試時,您可以創建一個會話並將所有請求設置爲使用相同的會話。

MockHttpSession session = new MockHttpSession(); 
request.setSession(session); 
相關問題