如何创建 ServletContext 的模拟属性



我有Servlet,它可以在数据库中添加用户。Servlet 使用模块的实例来处理他的别名DBJoint的数据库。并且 Servlet 从 ServletContext 获取DBJoint实例。

@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);
    }
}

在每个 Servlet 中,当我需要使用数据库时,我会调用ServletContext并通过键"db"获取DBJoint

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(User 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?如何测试这门课?谢谢!

你也需要包括这些

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

您正在模拟request对象上调用request.getServletContext()

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

当调用一个方法时,应该告诉模拟需要返回什么,你需要定义行为,就像你对DBJoinHandler模拟所做的那样。

要解决 NPE,请执行以下操作:

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

其中context可以是 ServletContext 模拟。

相关内容

最新更新