2014-04-10 59 views
1

我需要測試一個現在工作正常的servlet。測試Spring託管servlet

servlet需要使用一個Spring服務,所以它被修改爲這樣:

SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(
    this, config.getServletContext()); // ImageServlet.java line 49 

遷移後彈簧4,測試打破了,目前它拋出這個異常:

java.lang.IllegalStateException: 
No WebApplicationContext found: no ContextLoaderListener registered? 
at org.springframework.web.context.support.WebApplicationContextUtils. 
    getRequiredWebApplicationContext(WebApplicationContextUtils.java:84) 
at org.springframework.web.context.support.SpringBeanAutowiringSupport. 
    processInjectionBasedOnServletContext(SpringBeanAutowiringSupport.java:107) 
at package.ImageServlet.init(ImageServlet.java:49) 
at in.nasv.utils.ImageServletTest.accessingImageViaHttp(ImageServletTest.java:45) 

下面是ImageServletTest的代碼的部分:

// prepare servlet instance 
MockServletConfig config = new MockServletConfig(
    new MockServletContextPatched()); 
ImageServlet servlet = new ImageServlet(); 
servlet.init(config); // ImageServletTest, line 45 

而這種修補CLAS S(不是現在居然打補丁):

public class MockServletContextPatched extends MockServletContext{ } 

那我該怎麼做,以避免這種「IllegalStateException異常:沒有找到的WebApplicationContext:沒有註冊的ContextLoaderListener」 ?

+0

你真的需要調用'init()'方法來測試你的Servlet嗎?如果沒有,我建議你只是手動實例化你的Servlet和_inject_它的依賴關係,而不是依賴你的測試中的'SpringBeanAutowiringSupport'。 –

+0

偉大的方法,但它不適用於我的情況。Spring MockServletContext的功能非常有限(沒有setter和getters只返回固定值,dummy Spring!),所以我需要擴展它。我只能通過init()應用它() – joro

+0

Spring的'MockServletContext' ** does **有setter。你認爲Spring的'MockServletContext'有什麼限制?你定製的'MockServletContextPatched'有什麼特別之處? –

回答

0

我找到了解決方案。但足夠清楚,但一個解決方案。

現在Servlet的初始化是:

MockServletContext servletContext = new MockServletContextPatched(); 
MockServletConfig config = new MockServletConfig(servletContext); 
ImageServlet servlet = new ImageServlet(); 

ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("spring-data-app-context.xml"); 
DefaultListableBeanFactory dlbf = new DefaultListableBeanFactory(appContext.getBeanFactory()); 
GenericWebApplicationContext gwac = new GenericWebApplicationContext(dlbf);   
servletContext.setAttribute(GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, gwac); 
gwac.setServletContext(servletContext); 
gwac.refresh(); 

servlet.init(config); 

準備請求和在標準的方式響應:

MockHttpServletResponse response = new MockHttpServletResponse(); 

URL serverUrl = new URL(propertyExtendedService.getServerAddress(true)); 
MockHttpServletRequest request = new MockHttpServletRequest(); 
request.setRequestURI("/what-you-want"); 
request.setPathInfo("/" + TEST_IMAGE); 
request.setContentType("image/jpeg"); 
request.addHeader("Accept", "image/jpeg;image/jpg;"); 

最後一步是調用濾波器和斷言返回值:

servlet.doGet(request, response); 
assertEquals(response.getStatus(), 200); 
// assert everything you want 
+0

你絕對不應該加載兩個'ApplicationContext'。一個就足夠了。此外,_Spring TestContext Framework_已經爲您設置了「WebApplicationContext」的測試基礎架構(包括「MockServletContext」,「MockHttpServletRequest」和「MockHttpServletResponse」)。你看過那個嗎? –

+0

請參見[加載WebApplicationContext](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#testcontext-ctx-management-web)和[測試請求和會話(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#testcontext-web-scoped-beans)以獲取詳細信息。 –

0

更新updated documentation for getServletContext()現在在線。


這是沒有必要實現自定義MockServletContextPatched班只是配置Spring的MockServletContext自定義MIME類型。

由於Spring的MockServletContext使用Java Activation Framework(JAF)來實現ServletContext.getMimeType(String)方法,所以通過JAF的MimetypesFileTypeMap.addMimeTypes(String)方法配置自定義MIME類型非常簡單,如下所示。

MockServletContext mockServletContext = new MockServletContext(); 
MimetypesFileTypeMap mimetypesFileTypeMap = 
    (MimetypesFileTypeMap) MimetypesFileTypeMap.getDefaultFileTypeMap(); 
mimetypesFileTypeMap.addMimeTypes("text/enigma enigma"); 
assertEquals("text/enigma", mockServletContext.getMimeType("filename.enigma")); 

在上述基於JUnit的測試代碼,我配置的自定義的MIME類型"text/enigma"對於具有擴展.enigma文件。

希望這有助於!

問候,

山姆(Spring的TestContext框架的作者)

附:我創建了JIRA問題SPR-12126以改進MockServletContext的文檔。

+0

嗨,山姆。感謝我的解決方法。對不起,我放棄了這個測試(所有舊的servlet功能都被刪除了,所以它的測試也被放棄了),所以我可以測試它。你的方法似乎是一個優雅的方法。但是... – joro

+0

但我不確定是否更好。大多數開發人員會尋找一個setter,因爲常見的測試雙打很簡單並且具有硬編碼值。其他原因是JAF似乎並不常見,所以可能會跳過MimetypesFileTypeMap。但這是我的看法,我的方式是錯的。再次爲解決方案的10倍。 – joro