2014-03-24 3 views
7

Ich habe ein unabhängiges Projekt zum Schreiben von Testfällen; Das Problem ist, ich kann nicht HttpServletRequest, einfach simulieren, weil in meinem Servlet Anrufe wie getServletContext() als Testfälle sind von außerhalb Servlet-Container laufen. Es wird immer ein Fehler zurückgegeben, der besagt, dass kein Kontext gefunden wurde. Dies ist nur eine Abhängigkeit mit dem Servlet-Container. Es kann Hunderte geben. Zum Beispiel hängt initialContext.lookup() auch von einem Container ab.Wie man einen ServletContext anstelle von Servlet oder HttpServletRequest vortäuscht?

Wie kann ich mit Mockito einen Testfall in diesem Szenario schreiben? Bitte fragen Sie nicht nach einer Fehlermeldung; es ist eher ein logisches Problem als ein technisches Problem.

Wenn ich im Internet nach Tutorials suche, frage ich mich, ob ich etwas ernsthaft falsch mache. Niemand scheint dieses Problem schon einmal angetroffen zu haben ... Wie kann man HttpServletRequest verspotten, ohne jemals getServletContext() im Servlet aufgerufen zu haben? Ich meine ernsthaft, wie selten kann es sein?

+0

auch wenn Sie mich in die richtige Richtung zeigen kann, würde es ausreichen. – Vivek

+0

Wenn Sie den Frühling verwenden, haben sie alle eine Klasse MockHttpServletRequest http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/mock/web/MockHttpServletRequest.html – ndrone

Antwort

12

Sie haben eine Servlet-Implementierung, die die ServletContext verwendet, z.

public class SomeServlet extends HttpServlet{ 

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
     ServletContext servletContext = getServletContext(); 
     Object attribute = servletContext.getAttribute("test"); 
     System.out.println(attribute.toString()); 
    } 
} 

in diesem Fall haben Sie zwei Möglichkeiten der doGet Methode

Verwenden PowerMock des partitial mocking nur die getServletContext Methode zu verspotten zu testen.

@RunWith(PowerMockRunner.class) 
public class SomeServletTest { 

    @Test 
    public void onGet() throws ServletException, IOException{ 
     SomeServlet someServlet = PowerMock.createPartialMock(SomeServlet.class, "getServletContext"); 
     ServletContext servletContext = PowerMock.createNiceMock(ServletContext.class); 
     HttpServletRequest httpServletRequest = PowerMock.createNiceMock(HttpServletRequest.class); 
     HttpServletResponse httpServletResponse = PowerMock.createNiceMock(HttpServletResponse.class); 

     someServlet.getServletContext(); 
     PowerMock.expectLastCall().andReturn(servletContext); 

     servletContext.getAttribute("test"); 
     PowerMock.expectLastCall().andReturn("hello"); 

     PowerMock.replay(someServlet, servletContext, httpServletRequest, httpServletResponse); 

     someServlet.doGet(httpServletRequest, httpServletResponse); 
    } 
} 

oder ein einfacher Weg ist, um nur die getServletContext Methode außer Kraft setzen. In diesem Fall benötigen Sie keinen powermock. Sie können es einfach mit easymock machen. z.B.

public class SomeServletTest { 

    @Test 
    public void onGet() throws ServletException, IOException{ 
     HttpServletRequest httpServletRequest = EasyMock.createNiceMock(HttpServletRequest.class); 
     HttpServletResponse httpServletResponse = EasyMock.createNiceMock(HttpServletResponse.class); 
     final ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class); 
     SomeServlet someServlet = new SomeServlet(){ 
      public ServletContext getServletContext() { 
       return servletContext; // return the mock 
      } 
     }; 

     EasyMock.expect(servletContext.getAttribute("test")).andReturn("hello"); 
     EasyMock.replay(servletContext, httpServletRequest, httpServletResponse); 

     someServlet.doGet(httpServletRequest, httpServletResponse); 
    } 
} 

kann es 100 ist sein. wie initialContext.lookup() auch abhängig vom Container.

In diesem Fall können Sie entweder einen InitialContext Mock erstellen und diesen verwenden. Wenn Ihr Code ein neues InitialContext erstellt, z.

public void someMethod(){ 
    InitialContext context = new InitialContext(); 
    context.lookup(....); 
} 

Sie können einfach die InitialContext Instanziierung zu einem geschützten Methode extrahieren, die Sie in Ihren Tests außer Kraft setzen können, wie ich oben mit dem

public void someMethod(){ 
    InitialContext context = createInitialContext(); 
    context.lookup(....); 
} 

protected InitialContext createInitialContext(){ 
    return new InitialContext(); // can be overridden by a subclass 
           // and therefore by tests as well to 
           // return a mock 
} 

ServletContext zeigte Wenn Sie nicht über nicht wollen oder können Ändern Sie den Code auf diese Weise, dann können Sie Powermock zu intercept the constructor verwenden.

EDIT

Können Sie nach Ihren Mockito Code? Es wäre ein Vergnügen, da die Methoden anders benannt sind.

@Test 
public void onGet() throws ServletException, IOException { 
    HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); 
    HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class); 
    final ServletContext servletContext = Mockito.mock(ServletContext.class); 
    SomeServlet someServlet = new SomeServlet(){ 
    public ServletContext getServletContext() { 
     return servletContext; // return the mock 
    } 
    }; 

    Mockito.doReturn("hello").when(servletContext).getAttribute("test"); 

    someServlet.doGet(httpServletRequest, httpServletResponse); 
} 
+1

Sorry schrieb meine Antwort auf Verwenden Sie EasyMock. Gleiches gilt für Mockito. –

+1

wunderbar, sieht gut aus, ich gebe es einen Versuch morgen, danke sooo viel – Vivek

+1

danke Rene, es funktioniert auch mit Mockito. – Vivek