2017-06-19 115 views
1

我有在数据库中添加用户的Servlet。 Servlet使用模块的实例来处理数据库,他的别名为DBJoint。并且Servlet从ServletContext获得DBJoint的实例。如何创建ServletContext的mock属性?

@WebListener 
public class ContextListener implements ServletContextListener { 
    @Override 
    public void contextInitialized(ServletContextEvent servletContextEvent) { 
     final ServletContext servletContext = 
       servletContextEvent.getServletContext(); 

     final DBJoint joint = new DBJointHandler(
       "database_scripts", 
       "authentication_database"); 

     servletContext.setAttribute("db", joint); 
    } 
} 

而在当我需要与数据库我叫ServletContext和关键"db"得到DBJoint工作每个servlet。

public class AddUserServlet extends HttpServlet { 

    @Override 
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException { 

     req.setCharacterEncoding("UTF8"); 

     try { 

      final boolean success = addUserInDatabase(req); 

      if (success) req.setAttribute("serverAnswer", EDIT_SUCCESS.get()); 
      else req.setAttribute("serverAnswer", ERR_UNIQUE_L_P.get()); 

      req.getRequestDispatcher(ANSWER.get()) 
        .forward(req, resp); 

     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Addition user in database. 
    * 
    * @return true if addition success, else false. 
    */ 
    private boolean addUserInDatabase(final HttpServletRequest req) 
      throws SQLException { 

     final User user = getUserFromRequest(req); 
     return getDatabaseExecutor().addUserAndGetSuccess(user); 
    } 

    /** 
    * Extracts user's data from HttpServletRequest. 
    * 
    * @return user from request. 
    */ 
    private User getUserFromRequest(final HttpServletRequest req) { 
     return new User(
       req.getParameter("name"), 
       req.getParameter("login"), 
       req.getParameter("password"), 
       req.getParameter("email"), 
       req.getParameter("role") 
     ); 
    } 

    /** 
    * Get executor database requests. 
    */ 
    private ScriptExecutor getDatabaseExecutor() throws SQLException { 
     final DBJoint db = (DBJoint) getServletContext().getAttribute("db"); 
     return db.getDBScriptExecutor(); 
    } 
} 

我需要测试我的Servlet,并使用模仿对象,而不是原来的对象:

在这个测试中,我尝试验证什么身体的doPost调用ADDUSER(用户U)的数据库脚本的执行。但获得NPE。

@Test 
public void whenUserAddThenAddUserCall() throws ServletException, IOException, SQLException { 

    final AddUserServlet servlet = new AddUserServlet(); 

    //mock http. 
    HttpServletRequest request = mock(HttpServletRequest.class); 
    HttpServletResponse response = mock(HttpServletResponse.class); 

    User user = new User("name", "login", "password", "email"); 

    //mock database. 
    ScriptExecutor executor = mock(ScriptExecutor.class); 

    DBJoint joint = mock(DBJointHandler.class); 
    when(joint.getDBScriptExecutor()).thenReturn(executor); 


    final ServletContext context = request.getServletContext(); 
    //In this place I get NPE but why? 
    context.setAttribute("db", joint); 

    servlet.doPost(request, response); 

    verify(executor).addUser(user); 
} 

为什么我有NullPointerException?如何测试这个课程?谢谢!

回答

0

您需要包括这些以及

ServletContext context = mock(ServletContext .class) 
when(request.getServletContext()).thenReturn(context); 
0

您正在致电request.getServletContext()request对象这是一个模拟。

模拟对象不提供真正的方法实现。而不是真正的getServletContext()实现,该方法的stubbed版本被称为返回null。

一个模拟应该告诉它需要返回什么时调用一个方法,你需要定义行为就像你为DBJoinHandler模​​拟。

为了解决NPE,做这样的事情:

when(request.getServletContext()).thenReturn(context); 

其中context可能是一个ServletContext模拟。

+0

'时(executor.addUserAndGetSuccess(用户))thenReturn(真);'我得到'IllegalStateException异常:ServletConfig类一直没有initialized'我AddUserServlet调用'getDatabaseExecutor ()',这是失败的。我需要模拟ServletContext,因为'getDatabaseExecutor()'将被调用。 – Pavel

+0

当你在'request'模拟中调用getServletContext()方法时,你需要定义行为。试试这样:'when(request.getServletContext())。thenReturn(mock(ServletContext.class));' –