首页 > 解决方案 > 如何用 mockito 替换 dao 方法

问题描述

我想在 mockito 中更改方法中的 dao 功能时,我遇到了问题。

总是想要连接,我得到一个错误javax.naming.NoInitialContextException,DAO 类试图与数据源连接并获取环境上下文。

public class OrderingMainActionTest extends Mockito {

    @Mock
    HttpSession mockedSession = mock(HttpSession.class);

    @Mock
    OrderingMainAction applicationServiceBean;

    @Mock
    InitialContext ic;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void orderingActionByUserTest() throws ServletException, IOException, AppException, SQLException {
        HttpServletRequest request = mock(HttpServletRequest.class);
        HttpServletResponse response = mock(HttpServletResponse.class);
        OrderingMainAction ordering = new OrderingMainAction();
        UserDao userDao = mock(UserDao.class);

        when(request.getSession()).thenReturn(mockedSession);

        User user = new User();
        user.setId(1);

        when(mockedSession.getAttribute("user")).thenReturn(user);
        when(request.getParameter("checkedSeats")).thenReturn("1");
        when(userDao.getFullNameByUserId(anyInt())).thenReturn("test test");

        assertEquals(ordering.execute(request,response),"/login");
    }

}

我尝试测试的类

public class OrderingMainAction extends Action {

    private static final Logger LOG = Logger.getLogger(OrderingMainAction.class);

    @Override
    public String execute(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException, AppException {

        HttpSession session = request.getSession();
        if (session.getAttribute("user") == null) {
            return "/login";
        }

        LOG.trace("Info ordering ticket --> "
                + " Route " + session.getAttribute("userRoute") + ", "
                + " User: " + session.getAttribute("user") + ", "
                + " Carriage Number: " + request.getParameter("checkedCarriage") + ", "
                + " Seats List: " + Arrays.toString(request.getParameter("checkedSeats").split(" ")) + ", ");

        LOG.trace("rsb:" + session.getAttribute("userRoute"));
        RouteSearchBean route = (RouteSearchBean) session.getAttribute("userRoute");

        UserCheck userCheck = new UserCheck();
        UserDao userDao = new UserDao();
        String[] seatList = request.getParameter("checkedSeats").split(" ");
        userCheck.setIdUser(((User) session.getAttribute("user")).getId());
        try {
            userCheck.setInitials(userDao.getFullNameByUserId(
                    ((User) session.getAttribute("user")).getId())
            );
        } catch (DBException e) {
            throw new AppException(LocaleMessageUtil
                    .getMessageWithLocale(request, e.getMessage()));
        }
        userCheck.setNumCarriage(Integer.valueOf(request.getParameter("checkedCarriage")));
        userCheck.setIdRoute(route.getIdRoute());

        for (String numSeat : seatList) {
            for (int i = 0; i < route.getStationList().size() - 1; ++i) {
                userCheck.setDateEnd(route.getStationList().get(i).getTimeEnd());
                userCheck.setIdTrain(route.getTrain().getId());
                userCheck.setIdStation(route.getStationList().get(i).getIdStation());
                userCheck.setNumSeat(Integer.parseInt(numSeat));
                LOG.trace("INSERT for ordering --> " + userCheck);
                CheckDao.saveUserCheckInfo(userCheck);

            }
        }

        return "WEB-INF/jsp/booking/ordering.jsp";
    }
}

具有此问题方法的 DAO 类


    public String getFullNameByUserId(Integer idUser) throws DBException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        String initials = "";

        try {
            //DBUtil <-- There is a problem
            conn = DBUtil.getInstance().getDataSource().getConnection();
            pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");

数据库实用程序类

public final class DBUtil {

    private static final Logger LOG = Logger.getLogger(DBUtil.class);

    private static DBUtil instance;

    private DataSource ds;

    public static synchronized DBUtil getInstance() {
        if (instance == null) {
            instance = new DBUtil();
        }
        return instance;
    }

    private DBUtil(){
        try {
            Context initContext = new InitialContext();
            // Problem is here, and always throw the exception javax.naming.NoInitialContextException
            Context envContext = (Context) initContext.lookup("java:/comp/env");
            ds = (DataSource) envContext.lookup("jdbc/ResConDB");
            LOG.trace("Data source ==> " + ds);
        } catch (NamingException ex) {
            LOG.error(Messages.ERR_CANNOT_OBTAIN_DATA_SOURCE, ex);
            //throw new DBException(Messages.ERR_CANNOT_OBTAIN_DATA_SOURCE, ex);
        }
    }

    public DataSource getDataSource() {
        return ds;
    }

标签: javatestingservicemockito

解决方案


根据被测对象方法和断言,您似乎正在尝试模拟许多不必要的依赖项。

显示的断言

assertEquals(ordering.execute(request,response),"/login");

期望接收"/login",只有在以下条件下才会发生

//...

if (session.getAttribute("user") == null) {
    return "/login";
}

//...

表现如预期。

满足上述条件的测试必须看起来像

public class OrderingMainActionTest {

    @Test
    public void orderingActionByUserTest() throws ServletException, IOException, AppException, SQLException {
        //Arrange
        HttpServletRequest request = mock(HttpServletRequest.class);
        HttpSession mockedSession = mock(HttpSession.class);    
        when(request.getSession()).thenReturn(mockedSession);   
        when(mockedSession.getAttribute("user")).thenReturn(null);

        HttpServletResponse response = mock(HttpServletResponse.class);

        string expected = "/login";
        OrderingMainAction ordering = new OrderingMainAction();

        //Act
        String actual = ordering.execute(request, response);

        //Assert
        assertEquals(expected, actual);
    }

}

这让我相信这是一个需要更多澄清的XY 问题。


推荐阅读