controllers = new HashMap<>();
+
+ // 루트 경로
+ controllers.put(createKey(RequestPath.ROOT.getValue(), null), new ForwardController());
+
+ // 회원가입
+ controllers.put(createKey(RequestPath.USER_SIGNUP.getValue(), HttpMethod.POST), new UserSignupController());
+
+ // 로그인
+ controllers.put(createKey(RequestPath.USER_LOGIN.getValue(), HttpMethod.POST), new UserLoginController());
+
+ // 회원 목록
+ controllers.put(createKey(RequestPath.USER_LIST.getValue(), null), new UserListController());
+
+ return controllers;
+ }
+
+ public static String createKey(String path, HttpMethod method) {
+ if (method == null) {
+ return path;
+ }
+ return path + "_" + method.name();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/HttpRequestTest.java b/src/test/java/HttpRequestTest.java
new file mode 100644
index 0000000..92f6d43
--- /dev/null
+++ b/src/test/java/HttpRequestTest.java
@@ -0,0 +1,79 @@
+import http.HttpRequest;
+import http.enums.HttpMethod;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpRequestTest {
+
+ private static final String TEST_DIRECTORY = "src/test/resources/";
+
+ private BufferedReader bufferedReaderFromFile(String path) throws IOException {
+ return new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(path))));
+ }
+
+ @Test
+ @DisplayName("POST 요청을 파싱할 때 메서드, URL, 헤더, 바디가 올바르게 파싱되어야 한다")
+ public void parsePostRequestWithBodyAndHeaders() throws IOException {
+ // given
+ BufferedReader br = bufferedReaderFromFile(TEST_DIRECTORY + "request/post_request.txt");
+
+ // when
+ HttpRequest httpRequest = HttpRequest.from(br);
+
+ // then
+ assertEquals(HttpMethod.POST, httpRequest.getMethod());
+ assertEquals("/user/create", httpRequest.getUrl());
+ assertEquals("HTTP/1.1", httpRequest.getVersion());
+ assertEquals("localhost:8080", httpRequest.getHeader("Host"));
+ assertEquals(35, httpRequest.getContentLength());
+ assertNotNull(httpRequest.getBody());
+ assertTrue(httpRequest.getBody().contains("userId"));
+ }
+
+ @Test
+ @DisplayName("GET 요청을 파싱할 때 쿼리 파라미터와 쿠키가 올바르게 파싱되어야 한다")
+ public void parseGetRequestWithQueryParametersAndCookies() throws IOException {
+ // given
+ BufferedReader br = bufferedReaderFromFile(TEST_DIRECTORY + "request/get_request.txt");
+
+ // when
+ HttpRequest httpRequest = HttpRequest.from(br);
+
+ // then
+ assertEquals(HttpMethod.GET, httpRequest.getMethod());
+ assertEquals("/index.html?name=foden&age=26", httpRequest.getUrl());
+ assertEquals("name=foden&age=26", httpRequest.getQueryString());
+ assertEquals("HTTP/1.1", httpRequest.getVersion());
+ assertEquals("localhost:8080", httpRequest.getHeader("Host"));
+ assertEquals("logined=true", httpRequest.getCookie());
+ assertNull(httpRequest.getBody());
+ }
+
+ @Test
+ @DisplayName("잘못된 형식의 요청 라인이 주어질 때 예외가 발생해야 한다")
+ public void throwExceptionWhenInvalidRequestLineFormat() {
+ // given
+ BufferedReader br = new BufferedReader(new java.io.StringReader("INVALID REQUEST"));
+
+ // when & then
+ assertThrows(IllegalArgumentException.class, () -> HttpRequest.from(br));
+ }
+
+ @Test
+ @DisplayName("빈 요청 라인이 주어질 때 예외가 발생해야 한다")
+ public void throwExceptionWhenEmptyRequestLine() {
+ // given
+ BufferedReader br = new BufferedReader(new java.io.StringReader(""));
+
+ // when & then
+ assertThrows(IllegalArgumentException.class, () -> HttpRequest.from(br));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/HttpResponseTest.java b/src/test/java/HttpResponseTest.java
new file mode 100644
index 0000000..b88315f
--- /dev/null
+++ b/src/test/java/HttpResponseTest.java
@@ -0,0 +1,98 @@
+import http.HttpResponse;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpResponseTest {
+
+ private static final String TEST_DIRECTORY = "src/test/resources/response/";
+
+ private OutputStream outputStreamToFile(String path) throws IOException {
+ return Files.newOutputStream(Paths.get(path));
+ }
+
+ @Test
+ @DisplayName("forward 메서드로 HTML 파일을 전송할 때 올바른 HTTP 응답이 생성되어야 한다")
+ public void forwardHtmlFileWithCorrectHttpResponse() throws IOException {
+ // given
+ String outputPath = TEST_DIRECTORY + "forward_output.txt";
+ HttpResponse httpResponse = new HttpResponse(outputStreamToFile(outputPath));
+
+ // when
+ httpResponse.forward("/index.html");
+
+ // then
+ String responseContent = Files.readString(Paths.get(outputPath));
+ assertTrue(responseContent.contains("HTTP/1.1 200 OK"));
+ assertTrue(responseContent.contains("Content-Type: text/html"));
+ assertTrue(responseContent.contains("Content-Length:"));
+
+ // cleanup
+ Files.deleteIfExists(Paths.get(outputPath));
+ }
+
+ @Test
+ @DisplayName("redirect 메서드로 리다이렉트할 때 302 응답과 Location 헤더가 생성되어야 한다")
+ public void redirectWithCorrectLocationHeader() throws IOException {
+ // given
+ String outputPath = TEST_DIRECTORY + "redirect_output.txt";
+ HttpResponse httpResponse = new HttpResponse(outputStreamToFile(outputPath));
+
+ // when
+ httpResponse.redirect("/index.html");
+
+ // then
+ String responseContent = Files.readString(Paths.get(outputPath));
+ assertTrue(responseContent.contains("HTTP/1.1 302 Found"));
+ assertTrue(responseContent.contains("Location: /index.html"));
+
+ // cleanup
+ Files.deleteIfExists(Paths.get(outputPath));
+ }
+
+ @Test
+ @DisplayName("쿠키와 함께 리다이렉트할 때 Set-Cookie 헤더가 포함되어야 한다")
+ public void redirectWithCookieIncludesSetCookieHeader() throws IOException {
+ // given
+ String outputPath = TEST_DIRECTORY + "redirect_cookie_output.txt";
+ HttpResponse httpResponse = new HttpResponse(outputStreamToFile(outputPath));
+
+ // when
+ httpResponse.redirectWithCookie("/index.html", "logined=true");
+
+ // then
+ String responseContent = Files.readString(Paths.get(outputPath));
+ assertTrue(responseContent.contains("HTTP/1.1 302 Found"));
+ assertTrue(responseContent.contains("Set-Cookie: logined=true"));
+ assertTrue(responseContent.contains("Location: /index.html"));
+
+ // cleanup
+ Files.deleteIfExists(Paths.get(outputPath));
+ }
+
+ @Test
+ @DisplayName("404 에러 응답을 생성할 때 올바른 에러 메시지가 포함되어야 한다")
+ public void notFoundResponseWithErrorMessage() throws IOException {
+ // given
+ String outputPath = TEST_DIRECTORY + "notfound_output.txt";
+ HttpResponse httpResponse = new HttpResponse(outputStreamToFile(outputPath));
+
+ // when
+ httpResponse.notFound();
+
+ // then
+ String responseContent = Files.readString(Paths.get(outputPath));
+ assertTrue(responseContent.contains("HTTP/1.1 404 Not Found"));
+ assertTrue(responseContent.contains("Content-Type: text/html"));
+ assertTrue(responseContent.contains("404 Not Found"));
+
+ // cleanup
+ Files.deleteIfExists(Paths.get(outputPath));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/controller/ForwardControllerTest.java b/src/test/java/controller/ForwardControllerTest.java
new file mode 100644
index 0000000..5d7daca
--- /dev/null
+++ b/src/test/java/controller/ForwardControllerTest.java
@@ -0,0 +1,111 @@
+package controller;
+
+import http.HttpRequest;
+import http.HttpResponse;
+import http.enums.RequestPath;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+
+import static org.mockito.Mockito.*;
+
+public class ForwardControllerTest {
+
+ @Mock
+ private HttpRequest mockRequest;
+
+ @Mock
+ private HttpResponse mockResponse;
+
+ private final ForwardController controller = new ForwardController();
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ }
+
+ @Test
+ @DisplayName("루트 경로(/)로 요청하면 인덱스 페이지로 forward되어야 한다")
+ public void forwardToIndexForRootPath() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward(RequestPath.INDEX.getValue());
+ }
+
+ @Test
+ @DisplayName("일반 정적 파일 경로로 요청하면 해당 파일로 forward되어야 한다")
+ public void forwardToStaticFile() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/css/style.css");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward("/css/style.css");
+ }
+
+ @Test
+ @DisplayName("디렉토리 트래버설 공격(..)이 포함된 경로는 404 응답을 해야 한다")
+ public void returnNotFoundForDirectoryTraversalAttack() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/../../etc/passwd");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).notFound();
+ verify(mockResponse, never()).forward(anyString());
+ }
+
+ @Test
+ @DisplayName("파일이 존재하지 않으면 404 응답을 해야 한다")
+ public void returnNotFoundForNonExistentFile() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/nonexistent.html");
+ doThrow(new IOException("File not found")).when(mockResponse).forward("/nonexistent.html");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward("/nonexistent.html");
+ verify(mockResponse).notFound();
+ }
+
+ @Test
+ @DisplayName("HTML 파일 요청은 정상적으로 forward되어야 한다")
+ public void forwardHtmlFile() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/user/form.html");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward("/user/form.html");
+ }
+
+ @Test
+ @DisplayName("JS 파일 요청은 정상적으로 forward되어야 한다")
+ public void forwardJsFile() throws IOException {
+ // given
+ when(mockRequest.getPath()).thenReturn("/js/app.js");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward("/js/app.js");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/controller/UserListControllerTest.java b/src/test/java/controller/UserListControllerTest.java
new file mode 100644
index 0000000..2548972
--- /dev/null
+++ b/src/test/java/controller/UserListControllerTest.java
@@ -0,0 +1,84 @@
+package controller;
+
+import http.HttpRequest;
+import http.HttpResponse;
+import http.enums.HttpMethod;
+import http.enums.RequestPath;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+
+import static org.mockito.Mockito.*;
+
+public class UserListControllerTest {
+
+ @Mock
+ private HttpRequest mockRequest;
+
+ @Mock
+ private HttpResponse mockResponse;
+
+ private UserListController controller;
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ controller = new UserListController();
+ }
+
+ @Test
+ @DisplayName("로그인된 사용자가 사용자 목록에 접근하면 사용자 목록 페이지를 보여줘야 한다")
+ public void showUserListForLoggedInUser() throws IOException {
+ // given
+ when(mockRequest.getCookie("logined")).thenReturn("true");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward(RequestPath.USER_LIST_HTML.getValue());
+ }
+
+ @Test
+ @DisplayName("로그인되지 않은 사용자가 사용자 목록에 접근하면 로그인 페이지로 리다이렉트되어야 한다")
+ public void redirectToLoginForNonLoggedInUser() throws IOException {
+ // given
+ when(mockRequest.getCookie("logined")).thenReturn(null);
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.USER_LOGIN_HTML.getValue());
+ }
+
+ @Test
+ @DisplayName("다른 쿠키가 있지만 로그인 쿠키가 없는 사용자는 로그인 페이지로 리다이렉트되어야 한다")
+ public void redirectToLoginForUserWithOtherCookies() throws IOException {
+ // given
+ when(mockRequest.getCookie("logined")).thenReturn(null);
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.USER_LOGIN_HTML.getValue());
+ }
+
+ @Test
+ @DisplayName("logined=true를 포함한 복합 쿠키가 있는 사용자는 사용자 목록을 볼 수 있어야 한다")
+ public void showUserListForUserWithComplexCookieIncludingLogined() throws IOException {
+ // given
+ when(mockRequest.getCookie("logined")).thenReturn("true");
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).forward(RequestPath.USER_LIST_HTML.getValue());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/controller/UserLoginControllerTest.java b/src/test/java/controller/UserLoginControllerTest.java
new file mode 100644
index 0000000..6249e0f
--- /dev/null
+++ b/src/test/java/controller/UserLoginControllerTest.java
@@ -0,0 +1,92 @@
+package controller;
+
+import db.MemoryUserRepository;
+import http.HttpRequest;
+import http.HttpResponse;
+import http.enums.HttpMethod;
+import http.enums.RequestPath;
+import model.User;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+
+import static org.mockito.Mockito.*;
+
+public class UserLoginControllerTest {
+
+ @Mock
+ private HttpRequest mockRequest;
+
+ @Mock
+ private HttpResponse mockResponse;
+
+ private UserLoginController controller;
+ private MemoryUserRepository repository;
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ controller = new UserLoginController();
+ repository = MemoryUserRepository.getInstance();
+
+ // 테스트용 사용자 미리 등록
+ User testUser = new User("testuser", "1234", "홍길동", "test@example.com");
+ repository.addUser(testUser);
+ }
+
+ @Test
+ @DisplayName("올바른 계정 정보로 로그인하면 메인 페이지로 리다이렉트되어야 한다")
+ public void loginSuccessWithValidCredentials() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of("userId", "testuser", "password", "1234"));
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirectWithCookie(RequestPath.INDEX.getValue(), "logined=true");
+ }
+
+ @Test
+ @DisplayName("잘못된 비밀번호로 로그인하면 로그인 실패 페이지로 리다이렉트되어야 한다")
+ public void loginFailWithWrongPassword() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of("userId", "testuser", "password", "wrongpassword"));
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.USER_LOGIN_FAILED.getValue());
+ }
+
+ @Test
+ @DisplayName("존재하지 않는 사용자로 로그인하면 로그인 실패 페이지로 리다이렉트되어야 한다")
+ public void loginFailWithNonExistentUser() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of("userId", "nonexistent", "password", "1234"));
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.USER_LOGIN_FAILED.getValue());
+ }
+
+ @Test
+ @DisplayName("빈 파라미터로 로그인하면 로그인 실패 페이지로 리다이렉트되어야 한다")
+ public void loginFailWithEmptyParameters() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of());
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.USER_LOGIN_FAILED.getValue());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/controller/UserSignupControllerTest.java b/src/test/java/controller/UserSignupControllerTest.java
new file mode 100644
index 0000000..ce9b42f
--- /dev/null
+++ b/src/test/java/controller/UserSignupControllerTest.java
@@ -0,0 +1,87 @@
+package controller;
+
+import db.MemoryUserRepository;
+import http.HttpRequest;
+import http.HttpResponse;
+import http.enums.HttpMethod;
+import http.enums.RequestPath;
+import model.User;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+public class UserSignupControllerTest {
+
+ @Mock
+ private HttpRequest mockRequest;
+
+ @Mock
+ private HttpResponse mockResponse;
+
+ private UserSignupController controller;
+ private MemoryUserRepository repository;
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ controller = new UserSignupController();
+ repository = MemoryUserRepository.getInstance();
+ }
+
+ @Test
+ @DisplayName("POST 요청으로 유효한 사용자 정보를 전송하면 회원가입이 성공해야 한다")
+ public void signupSuccessWithPostRequest() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of(
+ "userId", "testuser",
+ "password", "1234",
+ "name", "홍길동",
+ "email", "test@example.com"
+ ));
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.INDEX.getValue());
+
+ User savedUser = repository.findUserById("testuser");
+ assertNotNull(savedUser, "사용자가 저장되어야 한다");
+ assertEquals("testuser", savedUser.getUserId());
+ assertEquals("1234", savedUser.getPassword());
+ assertEquals("홍길동", savedUser.getName());
+ assertEquals("test@example.com", savedUser.getEmail());
+ }
+
+ @Test
+ @DisplayName("POST 요청으로 다른 유효한 사용자 정보를 전송하면 회원가입이 성공해야 한다")
+ public void signupSuccessWithAnotherPostRequest() throws IOException {
+ // given
+ when(mockRequest.getParameters()).thenReturn(java.util.Map.of(
+ "userId", "getuser",
+ "password", "5678",
+ "name", "김철수",
+ "email", "get@example.com"
+ ));
+
+ // when
+ controller.execute(mockRequest, mockResponse);
+
+ // then
+ verify(mockResponse).redirect(RequestPath.INDEX.getValue());
+
+ User savedUser = repository.findUserById("getuser");
+ assertNotNull(savedUser, "사용자가 저장되어야 한다");
+ assertEquals("getuser", savedUser.getUserId());
+ assertEquals("5678", savedUser.getPassword());
+ assertEquals("김철수", savedUser.getName());
+ assertEquals("get@example.com", savedUser.getEmail());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/webserver/RequestMapperTest.java b/src/test/java/webserver/RequestMapperTest.java
new file mode 100644
index 0000000..c63c2e5
--- /dev/null
+++ b/src/test/java/webserver/RequestMapperTest.java
@@ -0,0 +1,91 @@
+package webserver;
+
+import controller.*;
+import http.enums.HttpMethod;
+import http.enums.RequestPath;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DisplayName("RequestMapper 테스트")
+class RequestMapperTest {
+
+ private RequestMapper requestMapper;
+
+ @BeforeEach
+ void setUp() {
+ requestMapper = new RequestMapper();
+ }
+
+ @Test
+ @DisplayName("루트 경로 요청 시 ForwardController를 반환한다")
+ void shouldReturnForwardControllerWhenRootPath() {
+ // given
+ String path = RequestPath.ROOT.getValue();
+ HttpMethod method = HttpMethod.GET;
+
+ // when
+ Controller controller = requestMapper.getController(path, method);
+
+ // then
+ assertInstanceOf(ForwardController.class, controller);
+ }
+
+ @Test
+ @DisplayName("POST /user/signup 요청 시 UserSignupController를 반환한다")
+ void shouldReturnUserSignupControllerWhenPostUserSignup() {
+ // given
+ String path = RequestPath.USER_SIGNUP.getValue();
+ HttpMethod method = HttpMethod.POST;
+
+ // when
+ Controller controller = requestMapper.getController(path, method);
+
+ // then
+ assertInstanceOf(UserSignupController.class, controller);
+ }
+
+ @Test
+ @DisplayName("POST /user/login 요청 시 UserLoginController를 반환한다")
+ void shouldReturnUserLoginControllerWhenPostUserLogin() {
+ // given
+ String path = RequestPath.USER_LOGIN.getValue();
+ HttpMethod method = HttpMethod.POST;
+
+ // when
+ Controller controller = requestMapper.getController(path, method);
+
+ // then
+ assertInstanceOf(UserLoginController.class, controller);
+ }
+
+ @Test
+ @DisplayName("/user/userList 요청 시 UserListController를 반환한다")
+ void shouldReturnUserListControllerWhenUserList() {
+ // given
+ String path = RequestPath.USER_LIST.getValue();
+ HttpMethod method = HttpMethod.GET;
+
+ // when
+ Controller controller = requestMapper.getController(path, method);
+
+ // then
+ assertInstanceOf(UserListController.class, controller);
+ }
+
+ @Test
+ @DisplayName("알 수 없는 경로 요청 시 ForwardController를 기본으로 반환한다")
+ void shouldReturnForwardControllerWhenUnknownPath() {
+ // given
+ String path = "/unknown/path";
+ HttpMethod method = HttpMethod.GET;
+
+ // when
+ Controller controller = requestMapper.getController(path, method);
+
+ // then
+ assertInstanceOf(ForwardController.class, controller);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/request/get_request.txt b/src/test/resources/request/get_request.txt
new file mode 100644
index 0000000..84a5224
--- /dev/null
+++ b/src/test/resources/request/get_request.txt
@@ -0,0 +1,5 @@
+GET /index.html?name=foden&age=26 HTTP/1.1
+Host: localhost:8080
+Connection: keep-alive
+Accept: text/html,application/xhtml+xml
+Cookie: logined=true
diff --git a/src/test/resources/request/post_request.txt b/src/test/resources/request/post_request.txt
new file mode 100644
index 0000000..021b529
--- /dev/null
+++ b/src/test/resources/request/post_request.txt
@@ -0,0 +1,7 @@
+POST /user/create HTTP/1.1
+Host: localhost:8080
+Connection: keep-alive
+Content-Length: 35
+Accept: */*
+
+userId=foden&password=0801&name=PSG
\ No newline at end of file
diff --git a/src/test/resources/response/test.html b/src/test/resources/response/test.html
new file mode 100644
index 0000000..ca01255
--- /dev/null
+++ b/src/test/resources/response/test.html
@@ -0,0 +1,10 @@
+
+
+
+ Test Page
+
+
+ Test HTML Content
+ This is a test page for HttpResponse testing.
+
+
\ No newline at end of file
diff --git a/webapp/user/form.html b/webapp/user/form.html
index 77a96ae..168cca2 100644
--- a/webapp/user/form.html
+++ b/webapp/user/form.html
@@ -55,7 +55,7 @@ Sign up
-