@SankaSanka

Как протестировать сервлет?

У меня есть сервлет

public class ConformPay extends HttpServlet {
	private static final Logger LOGGER = Logger.getLogger(ConformPay.class);
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String confirm = request.getParameter("confirm");
		String dtime = request.getParameter("delete");

		String userEmail = request.getUserPrincipal().getName();
		DBManager dbManager= new DBManagerService();
		if (dtime != null) {

			Boolean delPayResult = dbManager.delPayment(dtime);
			request.getSession().setAttribute("delPayResult", delPayResult);

		}
		if (confirm != null) {

			Boolean confPayResult = dbManager.confPayment(confirm, userEmail);
			dbManager.delPayment(confirm);
			request.getSession().setAttribute("confPayResult", confPayResult);
		}

		response.sendRedirect("./getpays");
	}

}

Я пытаюсь написать к нему тест

@Test
public void testServlet() throws Exception {
        HttpServletRequest request = mock(HttpServletRequest.class);       
        HttpServletResponse response = mock(HttpServletResponse.class);    
        Principal principal = mock(Principal.class);
        
        
     //   DBManager dbManager=mock(DBManagerService.class);
        DBManagerService dbManager =mock(DBManagerService.class);
        
        
        when(request.getParameter("confirm")).thenReturn("true");
        when(request.getParameter("delete")).thenReturn("time");   
        Boolean bool=true;
        PowerMockito.when(dbManager.delPayment(" 5")).thenReturn(bool);
        
        when(request.getUserPrincipal()).thenReturn(principal);

        StringWriter stringWriter = new StringWriter();
        PrintWriter writer = new PrintWriter(stringWriter);
        when(response.getWriter()).thenReturn(writer);

        new ConformPay().doPost(request, response);

        verify(request, atLeast(1)).getParameter("confirm"); 
        assertTrue(stringWriter.toString().contains("true"));
    }
}

Проблема в том, что я не могу замокать тот момент, когда сервлет лезет в dbManager.delPayment(dtime). Они там благополучно валится, потому что коннекшена к базе который настроен через пул томката у него естественно нет.

Как сделать так, чтоб он просто тестил сервлет, не пытаясь потрогать базу?
Если можно на пальцах, я совсем еще зеленая и это мой первый тест(

Заранее спасибо огромное)
  • Вопрос задан
  • 1294 просмотра
Решения вопроса 1
@ads83
Проблема в том, что твой сервлет создает каждый раз новый dbManager. Ему пофигу, что ты там мокаешь - он создает. каждый вызов. new DBManagerService()
Это ужас-ужас и за такое бьют линейкой по пальцам в реальном коде недопустимо

Стандартное решение - создать поле в классе и использовать code injection, т.е. прописать аннотацию @Autowired:
public class ConformPay extends HttpServlet {
  private static final Logger LOGGER = Logger.getLogger(ConformPay.class);
  private static final long serialVersionUID = 1L;

@Autowired
DBManager dbManager


Потом тебе надо указать Спрингу (или аналогу), где взять компонент DBManager.
В тесте ты указываешь, что вместо настоящего DBManager нужно использовать mock.
----
Другой вариант, менее трудоемкий, но и менее распространенный - это использовать мок на геттере. Так же создаешь в сервлете поле, создаешь/инжектируешь его в конструкторе и создаешь методDBManager getDBManager() {return dBManager);}. Потом в методе `doPost` обращаешься не к полю dBManager, а дергаешь геттер: getDBManager().delPayment(dtime);
В тесте же на своем сервлете ставишь заглушку на этот метод:
when(conformPay.getDBManager()).thenReturn(dbManagerMock)

Проблема в этом подходе в том, что тебе нужно не создавать заглушку для conformPay, а использовать настоящий класс с заглушкой. Почитай про метод spy(), а также почему его рекомендуют применять только в исключительных случаях.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@SankaSanka Автор вопроса
я переделала сервлет.
public class ConformPay extends HttpServlet {
	private static final Logger LOGGER = Logger.getLogger(ConformPay.class);
	private static final long serialVersionUID = 1L;
	private FactoryDAO factoryDAO = FactoryDAO.getInstance();

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		LOGGER.debug("/pays/confpay#dopost start");
		String confirm = request.getParameter("confirm");
		String dtime = request.getParameter("delete");

		LOGGER.debug("confirmed=" + confirm + " deleted=" + dtime);

		String userEmail = request.getUserPrincipal().getName();
		if (dtime != null) {

			Boolean delPayResult = factoryDAO.getTransactionsDao().delPayment(dtime);
			request.getSession().setAttribute("delPayResult", delPayResult);
			LOGGER.debug("payment was deleted.");
		}
		if (confirm != null) {

			Boolean confPayResult = factoryDAO.getTransactionsDao().confPayment(confirm, userEmail);
			factoryDAO.getTransactionsDao().delPayment(confirm);
			request.getSession().setAttribute("confPayResult", confPayResult);
			LOGGER.debug("payment was confirmed.");
		}

		response.sendRedirect("./getpays");
	}

}

теперь можно на него как-то тест написать?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы