简体   繁体   中英

How create mock Attribute of ServletContext?

I have Servlet which add users in database. Servlet use instance of module for work with database he's alias DBJoint . And Servlet get instance of DBJoint from ServletContext .

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

And in each Servlet when I need work with database I call ServletContext and get DBJoint by key "db" .

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

I need test my Servlet, and use mock object instead original object:

In this test I try verify what body doPost call addUser(User u) in executor of database script. But get 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);
}

Why I have NullPointerException ? How test this class? Thank You!

You are calling request.getServletContext() on the request object which is a mock.

Mocked objects do no provide real method implementations. Instead of the real getServletContext() implementation, a stubbed version of the method is called returning null.

A mock should be told what it needs to return when a method is called on it, you need to define behavior just like you did for the DBJoinHandler mock.

To solve the NPE, do something like this:

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

where context could be a ServletContext mock.

you need to include these as well

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM