diff --git a/app/src/main/java/com/techcourse/ControllerAdapter.java b/app/src/main/java/com/techcourse/ControllerAdapter.java new file mode 100644 index 0000000000..7905a4ffa3 --- /dev/null +++ b/app/src/main/java/com/techcourse/ControllerAdapter.java @@ -0,0 +1,18 @@ +package com.techcourse; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import webmvc.org.springframework.web.servlet.mvc.asis.Controller; + +public class ControllerAdapter implements HandlerAdapter { + + @Override + public boolean supports(Object handler) { + return (handler instanceof Controller); + } + + @Override + public String adapt(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + return ((Controller) handler).execute(request, response); + } +} diff --git a/app/src/main/java/com/techcourse/DispatcherServlet.java b/app/src/main/java/com/techcourse/DispatcherServlet.java index 277d8eed9a..f691289d06 100644 --- a/app/src/main/java/com/techcourse/DispatcherServlet.java +++ b/app/src/main/java/com/techcourse/DispatcherServlet.java @@ -12,26 +12,33 @@ public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class); + private static final String NOT_FOUND_VIEW = "404.jsp"; - private ManualHandlerMapping manualHandlerMapping; + private HandlerMappings handlerMappings; + private HandlerExecutor handlerExecutor; public DispatcherServlet() { } + public DispatcherServlet(HandlerMappings handlerMappings, HandlerExecutor handlerExecutor) { + this.handlerMappings = handlerMappings; + this.handlerExecutor = handlerExecutor; + } + @Override public void init() { - manualHandlerMapping = new ManualHandlerMapping(); - manualHandlerMapping.initialize(); + handlerMappings = new HandlerMappings(); + handlerExecutor = new HandlerExecutor(); + handlerMappings.init(); } @Override protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException { - final String requestURI = request.getRequestURI(); - log.debug("Method : {}, Request URI : {}", request.getMethod(), requestURI); + log.debug("Method : {}, Request URI : {}", request.getMethod(), request.getRequestURI()); try { - final var controller = manualHandlerMapping.getHandler(requestURI); - final var viewName = controller.execute(request, response); + String viewName = findViewName(request, response); + move(viewName, request, response); } catch (Throwable e) { log.error("Exception : {}", e.getMessage(), e); @@ -39,6 +46,14 @@ protected void service(final HttpServletRequest request, final HttpServletRespon } } + private String findViewName(HttpServletRequest request, HttpServletResponse response) throws Exception { + Object handler = handlerMappings.getHandler(request); + if (handler == null) { + return NOT_FOUND_VIEW; + } + return handlerExecutor.execute(request, response, handler); + } + private void move(final String viewName, final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (viewName.startsWith(JspView.REDIRECT_PREFIX)) { response.sendRedirect(viewName.substring(JspView.REDIRECT_PREFIX.length())); diff --git a/app/src/main/java/com/techcourse/HandlerAdapter.java b/app/src/main/java/com/techcourse/HandlerAdapter.java new file mode 100644 index 0000000000..f2da01d0e3 --- /dev/null +++ b/app/src/main/java/com/techcourse/HandlerAdapter.java @@ -0,0 +1,11 @@ +package com.techcourse; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public interface HandlerAdapter { + + boolean supports(Object handler); + + String adapt(HttpServletRequest request, final HttpServletResponse response, Object handler) throws Exception; +} diff --git a/app/src/main/java/com/techcourse/HandlerExecutionAdapter.java b/app/src/main/java/com/techcourse/HandlerExecutionAdapter.java new file mode 100644 index 0000000000..e3146686a7 --- /dev/null +++ b/app/src/main/java/com/techcourse/HandlerExecutionAdapter.java @@ -0,0 +1,20 @@ +package com.techcourse; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +public class HandlerExecutionAdapter implements HandlerAdapter { + + @Override + public boolean supports(Object handler) { + return (handler instanceof HandlerExecution); + } + + @Override + public String adapt(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + ModelAndView handle = ((HandlerExecution) handler).handle(request, response); + return (String) handle.getView(); + } +} diff --git a/app/src/main/java/com/techcourse/HandlerExecutor.java b/app/src/main/java/com/techcourse/HandlerExecutor.java new file mode 100644 index 0000000000..6a6bb7fa40 --- /dev/null +++ b/app/src/main/java/com/techcourse/HandlerExecutor.java @@ -0,0 +1,23 @@ +package com.techcourse; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.util.Set; + +public class HandlerExecutor { + + private static final Set handlerAdapters = Set.of( + new ControllerAdapter(), + new HandlerExecutionAdapter() + ); + + public String execute(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + for (HandlerAdapter handlerAdapter : handlerAdapters) { + if (handlerAdapter.supports(handler)) { + return handlerAdapter.adapt(request, response, handler); + } + } + throw new IllegalArgumentException("Not found handler adapter for handler : " + handler); + } +} diff --git a/app/src/main/java/com/techcourse/HandlerMappings.java b/app/src/main/java/com/techcourse/HandlerMappings.java new file mode 100644 index 0000000000..d2226f0448 --- /dev/null +++ b/app/src/main/java/com/techcourse/HandlerMappings.java @@ -0,0 +1,31 @@ +package com.techcourse; + +import jakarta.servlet.http.HttpServletRequest; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; + +import java.util.ArrayList; +import java.util.List; + +public class HandlerMappings { + + private List handlerMappings = new ArrayList<>(); + + public void init() { + handlerMappings.add(new AnnotationHandlerMapping()); + handlerMappings.add(new ManualHandlerMapping()); + for (HandlerMapping handlerMapping : handlerMappings) { + handlerMapping.initialize(); + } + } + + public Object getHandler(HttpServletRequest request) { + for (HandlerMapping handlerMapping : handlerMappings) { + Object handler = handlerMapping.getHandler(request); + if (handler != null) { + return handler; + } + } + return null; + } +} diff --git a/app/src/main/java/com/techcourse/ManualHandlerMapping.java b/app/src/main/java/com/techcourse/ManualHandlerMapping.java index a54863caf8..1f7c9757f9 100644 --- a/app/src/main/java/com/techcourse/ManualHandlerMapping.java +++ b/app/src/main/java/com/techcourse/ManualHandlerMapping.java @@ -1,15 +1,21 @@ package com.techcourse; -import com.techcourse.controller.*; +import com.techcourse.controller.legacy.LoginController; +import com.techcourse.controller.legacy.LoginViewController; +import com.techcourse.controller.legacy.LogoutController; +import com.techcourse.controller.legacy.RegisterController; +import com.techcourse.controller.legacy.RegisterViewController; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import webmvc.org.springframework.web.servlet.mvc.asis.Controller; import webmvc.org.springframework.web.servlet.mvc.asis.ForwardController; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; import java.util.HashMap; import java.util.Map; -public class ManualHandlerMapping { +public class ManualHandlerMapping implements HandlerMapping { private static final Logger log = LoggerFactory.getLogger(ManualHandlerMapping.class); @@ -28,7 +34,8 @@ public void initialize() { .forEach(path -> log.info("Path : {}, Controller : {}", path, controllers.get(path).getClass())); } - public Controller getHandler(final String requestURI) { + public Controller getHandler(HttpServletRequest request) { + String requestURI = request.getRequestURI(); log.debug("Request Mapping Uri : {}", requestURI); return controllers.get(requestURI); } diff --git a/app/src/main/java/com/techcourse/controller/LoginController.java b/app/src/main/java/com/techcourse/controller/legacy/LoginController.java similarity index 93% rename from app/src/main/java/com/techcourse/controller/LoginController.java rename to app/src/main/java/com/techcourse/controller/legacy/LoginController.java index 0428fe109e..79d004355e 100644 --- a/app/src/main/java/com/techcourse/controller/LoginController.java +++ b/app/src/main/java/com/techcourse/controller/legacy/LoginController.java @@ -1,5 +1,6 @@ -package com.techcourse.controller; +package com.techcourse.controller.legacy; +import com.techcourse.controller.UserSession; import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; import jakarta.servlet.http.HttpServletRequest; diff --git a/app/src/main/java/com/techcourse/controller/LoginViewController.java b/app/src/main/java/com/techcourse/controller/legacy/LoginViewController.java similarity index 89% rename from app/src/main/java/com/techcourse/controller/LoginViewController.java rename to app/src/main/java/com/techcourse/controller/legacy/LoginViewController.java index 86ec26cdce..f918736074 100644 --- a/app/src/main/java/com/techcourse/controller/LoginViewController.java +++ b/app/src/main/java/com/techcourse/controller/legacy/LoginViewController.java @@ -1,5 +1,6 @@ -package com.techcourse.controller; +package com.techcourse.controller.legacy; +import com.techcourse.controller.UserSession; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; diff --git a/app/src/main/java/com/techcourse/controller/LogoutController.java b/app/src/main/java/com/techcourse/controller/legacy/LogoutController.java similarity index 84% rename from app/src/main/java/com/techcourse/controller/LogoutController.java rename to app/src/main/java/com/techcourse/controller/legacy/LogoutController.java index 4642fd9450..7c44744e7c 100644 --- a/app/src/main/java/com/techcourse/controller/LogoutController.java +++ b/app/src/main/java/com/techcourse/controller/legacy/LogoutController.java @@ -1,5 +1,6 @@ -package com.techcourse.controller; +package com.techcourse.controller.legacy; +import com.techcourse.controller.UserSession; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import webmvc.org.springframework.web.servlet.mvc.asis.Controller; diff --git a/app/src/main/java/com/techcourse/controller/RegisterController.java b/app/src/main/java/com/techcourse/controller/legacy/RegisterController.java similarity index 94% rename from app/src/main/java/com/techcourse/controller/RegisterController.java rename to app/src/main/java/com/techcourse/controller/legacy/RegisterController.java index da62e5e8e9..fa282abdf6 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterController.java +++ b/app/src/main/java/com/techcourse/controller/legacy/RegisterController.java @@ -1,4 +1,4 @@ -package com.techcourse.controller; +package com.techcourse.controller.legacy; import com.techcourse.domain.User; import com.techcourse.repository.InMemoryUserRepository; diff --git a/app/src/main/java/com/techcourse/controller/RegisterViewController.java b/app/src/main/java/com/techcourse/controller/legacy/RegisterViewController.java similarity index 90% rename from app/src/main/java/com/techcourse/controller/RegisterViewController.java rename to app/src/main/java/com/techcourse/controller/legacy/RegisterViewController.java index 136962136d..370347a4dc 100644 --- a/app/src/main/java/com/techcourse/controller/RegisterViewController.java +++ b/app/src/main/java/com/techcourse/controller/legacy/RegisterViewController.java @@ -1,4 +1,4 @@ -package com.techcourse.controller; +package com.techcourse.controller.legacy; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/app/src/main/java/com/techcourse/controller/mvc/MvcForwardController.java b/app/src/main/java/com/techcourse/controller/mvc/MvcForwardController.java new file mode 100644 index 0000000000..c1cbe5fbeb --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/mvc/MvcForwardController.java @@ -0,0 +1,21 @@ +package com.techcourse.controller.mvc; + +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; + +@Controller +public class MvcForwardController { + + private static final Logger log = LoggerFactory.getLogger(MvcForwardController.class); + + @RequestMapping(value = "/", method = RequestMethod.GET) + public ModelAndView viewIndex(HttpServletRequest req, HttpServletResponse res) { + return new ModelAndView("/index.jsp"); + } +} diff --git a/app/src/main/java/com/techcourse/controller/mvc/MvcLoginController.java b/app/src/main/java/com/techcourse/controller/mvc/MvcLoginController.java new file mode 100644 index 0000000000..d46a1db7a5 --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/mvc/MvcLoginController.java @@ -0,0 +1,56 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.controller.UserSession; +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; + +@Controller +public class MvcLoginController { + + private static final Logger log = LoggerFactory.getLogger(MvcLoginController.class); + + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ModelAndView loginUser(HttpServletRequest req, HttpServletResponse res) { + if (UserSession.isLoggedIn(req.getSession())) { + return new ModelAndView("redirect:/index.jsp"); + } + return new ModelAndView( + InMemoryUserRepository.findByAccount(req.getParameter("account")) + .map(user -> { + log.info("User : {}", user); + return login(req, user); + }) + .orElse("redirect:/401.jsp") + ); + } + + private String login(final HttpServletRequest request, final User user) { + if (user.checkPassword(request.getParameter("password"))) { + HttpSession session = request.getSession(); + session.setAttribute(UserSession.SESSION_KEY, user); + return "redirect:/index.jsp"; + } + return "redirect:/401.jsp"; + } + + @RequestMapping(value = "/login", method = RequestMethod.GET) + public ModelAndView viewLogin(HttpServletRequest req, HttpServletResponse res) { + return new ModelAndView( + UserSession.getUserFrom(req.getSession()) + .map(user -> { + log.info("logged in {}", user.getAccount()); + return "redirect:/index.jsp"; + }) + .orElse("/login.jsp") + ); + } +} diff --git a/app/src/main/java/com/techcourse/controller/mvc/MvcLogoutController.java b/app/src/main/java/com/techcourse/controller/mvc/MvcLogoutController.java new file mode 100644 index 0000000000..2024dac46f --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/mvc/MvcLogoutController.java @@ -0,0 +1,25 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.controller.UserSession; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; + +@Controller +public class MvcLogoutController { + + private static final Logger log = LoggerFactory.getLogger(MvcLogoutController.class); + + @RequestMapping(value = "/logout", method = RequestMethod.POST) + public ModelAndView logoutUser(HttpServletRequest req, HttpServletResponse res) { + HttpSession session = req.getSession(); + session.removeAttribute(UserSession.SESSION_KEY); + return new ModelAndView("redirect:/"); + } +} diff --git a/app/src/main/java/com/techcourse/controller/mvc/MvcRegisterController.java b/app/src/main/java/com/techcourse/controller/mvc/MvcRegisterController.java new file mode 100644 index 0000000000..ef34119acf --- /dev/null +++ b/app/src/main/java/com/techcourse/controller/mvc/MvcRegisterController.java @@ -0,0 +1,34 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.domain.User; +import com.techcourse.repository.InMemoryUserRepository; +import context.org.springframework.stereotype.Controller; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import web.org.springframework.web.bind.annotation.RequestMapping; +import web.org.springframework.web.bind.annotation.RequestMethod; +import webmvc.org.springframework.web.servlet.ModelAndView; + +@Controller +public class MvcRegisterController { + + private static final Logger log = LoggerFactory.getLogger(MvcRegisterController.class); + + @RequestMapping(value = "/register", method = RequestMethod.POST) + public ModelAndView registerUser(HttpServletRequest req, HttpServletResponse res) { + User user = new User(2, + req.getParameter("account"), + req.getParameter("password"), + req.getParameter("email")); + InMemoryUserRepository.save(user); + + return new ModelAndView("redirect:/index.jsp"); + } + + @RequestMapping(value = "/register", method = RequestMethod.GET) + public ModelAndView viewRegister(HttpServletRequest req, HttpServletResponse res) { + return new ModelAndView("/register.jsp"); + } +} diff --git a/app/src/test/java/com/techcourse/ControllerAdapterTest.java b/app/src/test/java/com/techcourse/ControllerAdapterTest.java new file mode 100644 index 0000000000..ec67dd451c --- /dev/null +++ b/app/src/test/java/com/techcourse/ControllerAdapterTest.java @@ -0,0 +1,36 @@ +package com.techcourse; + +import com.techcourse.controller.legacy.RegisterViewController; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.mvc.asis.Controller; + +import static org.assertj.core.api.Assertions.assertThat; + +class ControllerAdapterTest { + + private ControllerAdapter controllerAdapter = new ControllerAdapter(); + + @Test + void supports() { + //given + Controller controller = new RegisterViewController(); + + //when + boolean supports = controllerAdapter.supports(controller); + + //then + assertThat(supports).isTrue(); + } + + @Test + void adapt() throws Exception { + //given + Controller controller = new RegisterViewController(); + + //when + String viewName = controllerAdapter.adapt(null, null, controller); + + //then + assertThat(viewName).isEqualTo("/register.jsp"); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/DispatcherServletTest.java b/app/src/test/java/com/techcourse/DispatcherServletTest.java new file mode 100644 index 0000000000..4878836df9 --- /dev/null +++ b/app/src/test/java/com/techcourse/DispatcherServletTest.java @@ -0,0 +1,60 @@ +package com.techcourse; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class DispatcherServletTest { + + @Test + void serviceIfRedirect() throws Exception { + //given + HandlerMappings handlerMappings = mock(HandlerMappings.class); + HandlerExecutor handlerExecutor = mock(HandlerExecutor.class); + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + + DispatcherServlet dispatcherServlet = new DispatcherServlet(handlerMappings, handlerExecutor); + + when(request.getMethod()).thenReturn("POST"); + when(handlerExecutor.execute(any(), any(), any())).thenReturn("redirect:/index.jsp"); + + //when + dispatcherServlet.service(request, response); + + //then + verify(handlerExecutor, times(1)).execute(any(), any(), any()); + verify(response, times(1)).sendRedirect(any()); + } + + @Test + void service() throws Exception { + //given + HandlerMappings handlerMappings = mock(HandlerMappings.class); + HandlerExecutor handlerExecutor = mock(HandlerExecutor.class); + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + RequestDispatcher requestDispatcher = mock(RequestDispatcher.class); + + DispatcherServlet dispatcherServlet = new DispatcherServlet(handlerMappings, handlerExecutor); + + when(request.getMethod()).thenReturn("GET"); + when(handlerExecutor.execute(any(), any(), any())).thenReturn("/index.jsp"); + when(request.getRequestDispatcher(any())).thenReturn(requestDispatcher); + + //when + dispatcherServlet.service(request, response); + + //then + verify(handlerExecutor, times(1)).execute(any(), any(), any()); + verify(requestDispatcher, times(1)).forward(any(), any()); + } +} diff --git a/app/src/test/java/com/techcourse/HandlerExecutionAdapterTest.java b/app/src/test/java/com/techcourse/HandlerExecutionAdapterTest.java new file mode 100644 index 0000000000..62d82db027 --- /dev/null +++ b/app/src/test/java/com/techcourse/HandlerExecutionAdapterTest.java @@ -0,0 +1,46 @@ +package com.techcourse; + +import com.techcourse.controller.mvc.MvcRegisterController; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +class HandlerExecutionAdapterTest { + + private HandlerExecutionAdapter handlerExecutionAdapter = new HandlerExecutionAdapter(); + + @Test + void supports() throws Exception { + //given + MvcRegisterController mvcRegisterController = MvcRegisterController.class.newInstance(); + Method method= mvcRegisterController.getClass() + .getDeclaredMethod("viewRegister", HttpServletRequest.class, HttpServletResponse.class); + HandlerExecution handlerExecution = new HandlerExecution(mvcRegisterController, method); + + //when + boolean supports = handlerExecutionAdapter.supports(handlerExecution); + + //then + assertThat(supports).isTrue(); + } + + @Test + void adapt() throws Exception { + //given + MvcRegisterController mvcRegisterController = MvcRegisterController.class.newInstance(); + Method method= mvcRegisterController.getClass() + .getDeclaredMethod("viewRegister", HttpServletRequest.class, HttpServletResponse.class); + HandlerExecution handlerExecution = new HandlerExecution(mvcRegisterController, method); + + //when + String viewName = handlerExecutionAdapter.adapt(null, null, handlerExecution); + + //then + assertThat(viewName).isEqualTo("/register.jsp"); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/HandlerExecutorTest.java b/app/src/test/java/com/techcourse/HandlerExecutorTest.java new file mode 100644 index 0000000000..ea96dbaa9a --- /dev/null +++ b/app/src/test/java/com/techcourse/HandlerExecutorTest.java @@ -0,0 +1,58 @@ +package com.techcourse; + +import com.techcourse.controller.legacy.RegisterViewController; +import com.techcourse.controller.mvc.MvcRegisterController; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.mvc.asis.Controller; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +import java.lang.reflect.Method; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class HandlerExecutorTest { + + @Test + void executeIfControllerHandler() throws Exception { + //given + HandlerExecutor handlerExecutor = new HandlerExecutor(); + Controller controller = RegisterViewController.class.newInstance(); + + //when + String viewName = handlerExecutor.execute(null, null, controller); + + //then + assertEquals("/register.jsp", viewName); + } + + @Test + void executeIfHandlerExecution() throws Exception { + //given + HandlerExecutor handlerExecutor = new HandlerExecutor(); + + MvcRegisterController mvcRegisterController = MvcRegisterController.class.newInstance(); + Method method= mvcRegisterController.getClass() + .getDeclaredMethod("viewRegister", HttpServletRequest.class, HttpServletResponse.class); + HandlerExecution handlerExecution = new HandlerExecution(mvcRegisterController, method); + + //when + String viewName = handlerExecutor.execute(null, null, handlerExecution); + + //then + assertEquals("/register.jsp", viewName); + } + + @Test + void executeIfNoneHandler() throws Exception { + //given + HandlerExecutor handlerExecutor = new HandlerExecutor(); + + //when + String viewName = handlerExecutor.execute(null, null, null); + + //then + assertEquals("404.jsp", viewName); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/controller/mvc/ControllerTest.java b/app/src/test/java/com/techcourse/controller/mvc/ControllerTest.java new file mode 100644 index 0000000000..116b29f9f7 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/mvc/ControllerTest.java @@ -0,0 +1,16 @@ +package com.techcourse.controller.mvc; + +import org.junit.jupiter.api.BeforeEach; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; + +public abstract class ControllerTest { + + protected HandlerMapping handlerMapping; + + @BeforeEach + void setUp() { + handlerMapping = new AnnotationHandlerMapping("com.techcourse.controller"); + handlerMapping.initialize(); + } +} diff --git a/app/src/test/java/com/techcourse/controller/mvc/MvcForwardControllerTest.java b/app/src/test/java/com/techcourse/controller/mvc/MvcForwardControllerTest.java new file mode 100644 index 0000000000..b2ce1efde9 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/mvc/MvcForwardControllerTest.java @@ -0,0 +1,47 @@ +package com.techcourse.controller.mvc; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class MvcForwardControllerTest extends ControllerTest { + + private static final MvcForwardController mvcForwardController = new MvcForwardController(); + + @Nested + class viewIndex { + @Test + void getHandlerIfViewIndex() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/"); + when(request.getMethod()).thenReturn("GET"); + Method viewIndex = MvcForwardController.class.newInstance().getClass() + .getDeclaredMethod("viewIndex", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(viewIndex); + } + + @Test + void viewRegister() { + //given, when + ModelAndView modelAndView = mvcForwardController.viewIndex(null, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("/index.jsp"); + } + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/controller/mvc/MvcLoginControllerTest.java b/app/src/test/java/com/techcourse/controller/mvc/MvcLoginControllerTest.java new file mode 100644 index 0000000000..eba85f43be --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/mvc/MvcLoginControllerTest.java @@ -0,0 +1,157 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.controller.UserSession; +import com.techcourse.domain.User; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class MvcLoginControllerTest extends ControllerTest { + + private final MvcLoginController mvcLoginController = new MvcLoginController(); + + @Nested + class LoginUser { + @Test + void getHandlerIfLoginUser() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/login"); + when(request.getMethod()).thenReturn("POST"); + Method loginUser = MvcLoginController.class.newInstance().getClass() + .getDeclaredMethod("loginUser", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(loginUser); + } + + @Test + void loginUserIfAlreadyLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(httpSession.getAttribute(UserSession.SESSION_KEY)) + .thenReturn(new User(1, "moomin", "password", "moomin@gmail.com")); + + //when + ModelAndView modelAndView = mvcLoginController.loginUser(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("redirect:/index.jsp"); + } + + @Test + void loginUserSuccessIfNoneLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(request.getParameter("account")).thenReturn("gugu"); + when(request.getParameter("password")).thenReturn("password"); + + //when + ModelAndView modelAndView = mvcLoginController.loginUser(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("redirect:/index.jsp"); + } + + @Test + void loginUserInCorrectPasswordIfNoneLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(request.getParameter("account")).thenReturn("gugu"); + when(request.getParameter("password")).thenReturn("wrong"); + + //when + ModelAndView modelAndView = mvcLoginController.loginUser(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("redirect:/401.jsp"); + } + + @Test + void loginUserInCorrectAccountIfNoneLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(httpSession.getAttribute(UserSession.SESSION_KEY)) + .thenReturn(null); + when(request.getParameter("account")).thenReturn("wrong"); + + //when + ModelAndView modelAndView = mvcLoginController.loginUser(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("redirect:/401.jsp"); + } + } + + @Nested + class ViewLogin { + @Test + void getHandlerIfViewLogin() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/login"); + when(request.getMethod()).thenReturn("GET"); + Method viewUser = MvcLoginController.class.newInstance().getClass() + .getDeclaredMethod("viewLogin", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(viewUser); + } + + @Test + void viewLoginIfAlreadyLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(httpSession.getAttribute(UserSession.SESSION_KEY)) + .thenReturn(new User(1, "moomin", "password", "moomin@gmail.com")); + + //when + ModelAndView modelAndView = mvcLoginController.viewLogin(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("redirect:/index.jsp"); + } + + @Test + void viewLoginIfNoneLogin() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + when(httpSession.getAttribute(UserSession.SESSION_KEY)) + .thenReturn(null); + + //when + ModelAndView modelAndView = mvcLoginController.viewLogin(request, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("/login.jsp"); + } + } +} diff --git a/app/src/test/java/com/techcourse/controller/mvc/MvcLogoutControllerTest.java b/app/src/test/java/com/techcourse/controller/mvc/MvcLogoutControllerTest.java new file mode 100644 index 0000000000..48ba920023 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/mvc/MvcLogoutControllerTest.java @@ -0,0 +1,60 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.controller.UserSession; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.AnnotationHandlerMapping; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerMapping; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class MvcLogoutControllerTest extends ControllerTest { + + private static final MvcLogoutController mvcLogoutController = new MvcLogoutController(); + + @Nested + class LogoutUser { + @Test + void getHandlerIfLogoutUser() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/logout"); + when(request.getMethod()).thenReturn("POST"); + Method logoutUser = MvcLogoutController.class.newInstance().getClass() + .getDeclaredMethod("logoutUser", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(logoutUser); + } + + @Test + void logoutUser() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession httpSession = mock(HttpSession.class); + when(request.getSession()).thenReturn(httpSession); + + //when + ModelAndView modelAndView = mvcLogoutController.logoutUser((request), null); + + //then + verify(httpSession, times(1)).removeAttribute(UserSession.SESSION_KEY); + assertThat(modelAndView.getView()).isEqualTo("redirect:/"); + } + } +} \ No newline at end of file diff --git a/app/src/test/java/com/techcourse/controller/mvc/MvcRegisterControllerTest.java b/app/src/test/java/com/techcourse/controller/mvc/MvcRegisterControllerTest.java new file mode 100644 index 0000000000..48e5521da2 --- /dev/null +++ b/app/src/test/java/com/techcourse/controller/mvc/MvcRegisterControllerTest.java @@ -0,0 +1,86 @@ +package com.techcourse.controller.mvc; + +import com.techcourse.repository.InMemoryUserRepository; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import webmvc.org.springframework.web.servlet.ModelAndView; +import webmvc.org.springframework.web.servlet.mvc.tobe.HandlerExecution; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class MvcRegisterControllerTest extends ControllerTest { + + private static final MvcRegisterController mvcRegisterController = new MvcRegisterController(); + + @Nested + class RegisterUser { + @Test + void getHandlerIfRegisterUser() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/register"); + when(request.getMethod()).thenReturn("POST"); + Method registerUser = MvcRegisterController.class.newInstance().getClass() + .getDeclaredMethod("registerUser", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(registerUser); + } + + @Test + void registerUser() { + //given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getParameter("account")).thenReturn("moomin"); + when(request.getParameter("password")).thenReturn("password"); + when(request.getParameter("email")).thenReturn("moomin@gmail.com"); + + //when + ModelAndView modelAndView = mvcRegisterController.registerUser(request, null); + + //then + assertAll( + () -> assertThat(InMemoryUserRepository.findByAccount("moomin")).isPresent(), + () -> assertThat(modelAndView.getView()).isEqualTo("redirect:/index.jsp") + ); + } + } + + @Nested + class ViewRegister { + @Test + void getHandlerIfViewRegister() throws Exception { + // given + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getRequestURI()).thenReturn("/register"); + when(request.getMethod()).thenReturn("GET"); + Method viewRegister = MvcRegisterController.class.newInstance().getClass() + .getDeclaredMethod("viewRegister", HttpServletRequest.class, HttpServletResponse.class); + + // when + HandlerExecution handlerExecution = (HandlerExecution) handlerMapping.getHandler(request); + + // then + assertThat(handlerExecution.getMethod()).isEqualTo(handlerExecution.getMethod()).isEqualTo(viewRegister); + } + + @Test + void viewRegister() { + //given, when + ModelAndView modelAndView = mvcRegisterController.viewRegister(null, null); + + //then + assertThat(modelAndView.getView()).isEqualTo("/register.jsp"); + } + } +} \ No newline at end of file diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java index ff8e24553f..ec371d84cc 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/ModelAndView.java @@ -6,10 +6,10 @@ public class ModelAndView { - private final View view; + private final Object view; private final Map model; - public ModelAndView(final View view) { + public ModelAndView(final Object view) { this.view = view; this.model = new HashMap<>(); } @@ -27,7 +27,7 @@ public Map getModel() { return Collections.unmodifiableMap(model); } - public View getView() { + public Object getView() { return view; } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java index 40a0c82582..db16c6d0b5 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/AnnotationHandlerMapping.java @@ -1,8 +1,6 @@ package webmvc.org.springframework.web.servlet.mvc.tobe; -import context.org.springframework.stereotype.Controller; import jakarta.servlet.http.HttpServletRequest; -import org.reflections.Reflections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import web.org.springframework.web.bind.annotation.RequestMapping; @@ -13,10 +11,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -public class AnnotationHandlerMapping { +public class AnnotationHandlerMapping implements HandlerMapping { private static final Logger log = LoggerFactory.getLogger(AnnotationHandlerMapping.class); @@ -29,41 +25,30 @@ public AnnotationHandlerMapping(final Object... basePackage) { } public void initialize() { - log.info("Initialized AnnotationHandlerMapping!"); - Reflections reflections = new Reflections(basePackage); - Set> controllers = reflections.getTypesAnnotatedWith(Controller.class); - List requestMappingMethods = mapRequestMappingMethods(controllers); + ControllerScanner controllerScanner = new ControllerScanner(); + RequestMappingScanner requestMappingScanner = new RequestMappingScanner(); - putHandlerExecutions(requestMappingMethods); - } + Set> controllers = controllerScanner.scan(basePackage); + Map, Object> instances = controllerScanner.createControllerInstance(controllers); + + List requestMappingMethods = requestMappingScanner.scanRequestMappingMethods(controllers); - private List mapRequestMappingMethods(Set> controllers) { - return controllers.stream() - .map(Class::getDeclaredMethods).flatMap(Stream::of) - .filter(method -> method.isAnnotationPresent(RequestMapping.class)) - .collect(Collectors.toList()); + putHandlerExecutions(requestMappingMethods, instances); + log.info("Initialized AnnotationHandlerMapping!"); } - private void putHandlerExecutions(List requestMappingMethods) { - requestMappingMethods.forEach(method -> { - Object controller = createControllerInstance(method); + private void putHandlerExecutions(List requestMappingMethods, Map, Object> instances) { + for (Method method : requestMappingMethods) { + Object controller = instances.get(method.getDeclaringClass()); RequestMapping annotation = method.getAnnotation(RequestMapping.class); String path = annotation.value(); RequestMethod[] requestMethods = annotation.method(); RequestMethod requestMethod = RequestMethod.valueOf(requestMethods[0].name()); handlerExecutions.put(new HandlerKey(path, requestMethod), new HandlerExecution(controller, method)); - }); - } - - private Object createControllerInstance(Method method) { - try { - return method.getDeclaringClass().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalArgumentException(e); } } - public Object getHandler(final HttpServletRequest request) { + public Object getHandler(HttpServletRequest request) { RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); HandlerKey handlerKey = new HandlerKey(request.getRequestURI(), requestMethod); diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScanner.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScanner.java new file mode 100644 index 0000000000..90dbc72507 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScanner.java @@ -0,0 +1,29 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import context.org.springframework.stereotype.Controller; +import org.reflections.Reflections; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class ControllerScanner { + + public Set> scan(Object... basePackage) { + Reflections reflections = new Reflections(basePackage); + Set> controllers = reflections.getTypesAnnotatedWith(Controller.class); + return controllers; + } + + public Map, Object> createControllerInstance(Set> controllers) { + try { + Map, Object> instances = new HashMap<>(); + for (Class controller : controllers) { + instances.put(controller, controller.newInstance()); + } + return instances; + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java index 0d4105fd2a..a06e670576 100644 --- a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerExecution.java @@ -19,4 +19,8 @@ public HandlerExecution(Object controller, Method method) { public ModelAndView handle(final HttpServletRequest request, final HttpServletResponse response) throws Exception { return (ModelAndView) method.invoke(controller, request, response); } + + public Method getMethod() { + return method; + } } diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java new file mode 100644 index 0000000000..2fd9df144a --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/HandlerMapping.java @@ -0,0 +1,10 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import jakarta.servlet.http.HttpServletRequest; + +public interface HandlerMapping { + + void initialize(); + + Object getHandler(HttpServletRequest request); +} diff --git a/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScanner.java b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScanner.java new file mode 100644 index 0000000000..38ff90c683 --- /dev/null +++ b/mvc/src/main/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScanner.java @@ -0,0 +1,19 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import web.org.springframework.web.bind.annotation.RequestMapping; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class RequestMappingScanner { + + public List scanRequestMappingMethods(Set> controllers) { + return controllers.stream() + .map(Class::getDeclaredMethods).flatMap(Stream::of) + .filter(method -> method.isAnnotationPresent(RequestMapping.class)) + .collect(Collectors.toList()); + } +} diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScannerTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScannerTest.java new file mode 100644 index 0000000000..900221c62a --- /dev/null +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/ControllerScannerTest.java @@ -0,0 +1,37 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import context.org.springframework.stereotype.Controller; +import org.junit.jupiter.api.Test; +import org.reflections.Reflections; + +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class ControllerScannerTest { + + private static final String BASE_PACKAGE = "samples"; + + private ControllerScanner controllerScanner = new ControllerScanner(); + + @Test + void scan() { + //given + Set> controllers = controllerScanner.scan(BASE_PACKAGE); + + //when, then + assertThat(controllers.size()).isEqualTo(1); + } + + @Test + void createControllerInstance() { + //given + Reflections reflections = new Reflections(BASE_PACKAGE); + Set> controllers = reflections.getTypesAnnotatedWith(Controller.class); + + Map, Object> controllerInstance = controllerScanner.createControllerInstance(controllers); + + assertThat(controllerInstance.size()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScannerTest.java b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScannerTest.java new file mode 100644 index 0000000000..14836dba55 --- /dev/null +++ b/mvc/src/test/java/webmvc/org/springframework/web/servlet/mvc/tobe/RequestMappingScannerTest.java @@ -0,0 +1,30 @@ +package webmvc.org.springframework.web.servlet.mvc.tobe; + +import context.org.springframework.stereotype.Controller; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.reflections.Reflections; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; + +class RequestMappingScannerTest { + + private static final String BASE_PACKAGE = "samples"; + + private final RequestMappingScanner requestMappingScanner = new RequestMappingScanner(); + + @Test + void scanRequestMappingMethods() { + //given + Reflections reflections = new Reflections(BASE_PACKAGE); + Set> controllers = reflections.getTypesAnnotatedWith(Controller.class); + + //when + List methods = requestMappingScanner.scanRequestMappingMethods(controllers); + + //then + Assertions.assertThat(methods.size()).isEqualTo(2); + } +} \ No newline at end of file