게시판 페이지를 만들기 위해 ArticleControllerTest를 정의해 주었다.
package com.fastcampus.projectboard.controller;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@DisplayName("View 컨트롤러 - 게시글")
@WebMvcTest(ArticleController.class) //컨트롤러가 여러개 있을때, ArticleController만 테스트한다.
class ArticleControllerTest {
private final MockMvc mvc;
public ArticleControllerTest(@Autowired MockMvc mvc) {
this.mvc = mvc;
}
@DisplayName("[view] [GET] 게시글 리스트 (게시판) 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleView_thenReturnsArticlesView() throws Exception {
//Given
//When & Then
mvc.perform(get("/articles"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML)) //exactmatch를 피하기위해 CompatibleWith를 사용
.andExpect(view().name("articles/index"))
.andExpect(model().attributeExists("articles"));
}
@Disabled("구현 중")
@DisplayName("[view][GET] 게시글 상세 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleView_thenReturnsArticleView() throws Exception {
//Given
//When & Then
mvc.perform(get("/articles/1"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(model().attributeExists("articles"));
}
@Disabled("구현 중")
@DisplayName("[view][GET] 게시글 검색 전용 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleSearchView_thenReturnsArticleSearchView() throws Exception {
//Given
//When & Then
mvc.perform(get("/articles/search"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(model().attributeExists("articles/search"));
}
@Disabled("구현 중")
@DisplayName("[view][GET] 게시글 해시태그 검색 페이지 - 정상 호출")
@Test
public void givenNothing_whenRequestingArticleHashtagSearchView_thenReturnsArticleHashtagSearchView() throws Exception {
//Given
//When & Then
mvc.perform(get("/articles/search-hashtag"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(model().attributeExists("articles/search-hashtag"));
}
}
ArticleController의 코드는 아래와 같다.
articles라는 요청이왔을때 articles 레포지토리의 index.html을 불러온다.
index.html은 다음과 같다.
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>게시판 페이지</title>
</head>
<body>
<header th:replace="header :: header"></header>
<main>
<form>
<label for="search-type"hidden>유형</label>
<select id="search-type" name="search-type">
<option>제목</option>
<option>본문</option>
<option>ID</option>
<option>닉네임</option>
<option>해시태그</option>
</select>
<label for="search-value" hidden>검색어</label>
<input id="search-value" type="search" placeholder="검색어..." name="search-value">
<button type="submit">검색</button>
</form>
<table>
<thead>
<tr>
<th>제목</th>
<th>해시태그</th>
<th>작성자</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
<tr>
<td>첫글</td>
<td>#java</td>
<td>ttaho</td>
<td>2022-01-01</td>
</tr>
<tr>
<td>두번쩨글</td>
<td>#Spring</td>
<td>ttaho</td>
<td>2022-01-02</td>
</tr>
<tr>
<td>세번쨰글</td>
<td>#java</td>
<td>ttaho</td>
<td>2022-01-03</td>
</tr>
</tbody>
</table>
<nav>
<table>
<tr>
<td>previous</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>next</td>
</tr>
</table>
</nav>
</main>
<footer th:replace="footer :: footer"></footer>
</body>
</html>
header와 footer의 내용은 현재 진행중인 게시판 페이지 외에 공통적으로 필요한 내용이므로 thymeleaf 문법을 사용하여 header.html과 footer.html을 뿌려주는 방법을 사용하였다.
header.html, footer.html
서비스를 run시켰을때, http://localhost:8080/articles 를 요청하면 아래의 화면을 볼 수 있다.