티스토리 뷰
[ 1 . MockMVC ] (*****)
더보기
[ + 코드 보기 ]
package org.zerock.myapp.controller;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
// JUNIT 5
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/root-context.xml",
"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
// + Spring MVC Controller를 테스트 하기 위해서는
// + 반드시 아래의 어노테이션을 붙여야 한다.
@WebAppConfiguration // (****)
public class BoardControllerTests {
@Autowired
private WebApplicationContext ctx;
// + WebApplicationContext는 스프링 빈즈 컨테이너의 구현 객체이다. (***)
// + 컨트롤러를 테스트 하기 위해서는 스프링 빈즈 컨테이너를 주입 받아야 한다.
// ===========================================================================
@BeforeAll
public void beforeAll() {
log.trace("beforeAll() invoked.");
} // beforeAll
// ===========================================================================
//@Disabled
@Test
@Order(1)
@DisplayName("1.testList")
@Timeout(value=5, unit = TimeUnit.SECONDS)
public void testList() throws Exception {
log.trace("testList() invoked.");
// ===========================================================================
// + 표현계층의 사용자 정의 Controller에 대한 테스트를 수행 시, 핵심은 WAS 구동 없이 테스트 필요 :
// + (1) @WebAppConfiguration 어노테이션
// + (2) MockMVC 클래스( 가상의 웹 브라우저 ) 사용법 :
// + 가. Spring Bean Container( WebApplicationContext를 주입받아야 한다. )
// + 나. '가'의 주입받은 객체를 이용해서, MockMvcBuilder 객체를 우선 생성
// + 다. '나'의 MockMvcBuilders란 Helper Class의 정적 메소드를 이용하여, MockMvcBuilder 객체를 얻는다.
// + 라. '다'에서 얻은 MockMvcBuilder.build() 메소드를 통해 MockMvc 객체를 얻는다.
// + 마. 'MockMvcBuilders' Helper Class의 정적 메소드를 이용해서, MockMvcRequestBuilder 객체를 얻는다.
// + 바. 'MockMvc'와 '마'에서 얻어낸, 'MockMvcRequestBuilder' 2개의 객체를 가지고 실제 가상의 요청(request)을 전송
// + - MockMvc.perform(MockMvcRequestBuilder) 메소드 호출로 수행
// + - 테스트 대상인 Controller의 핸들러 메소드가 수행되면서,
// + - 그 결과로 2가지의 정보를 얻게 된다. ( 1. Model 2. 뷰이름 )
// + 사. '바'에서 얻은 2가지 정보 중 필요로 하는 정보를 얻어내서 사용
// ===========================================================================
// + MockMvcBuilders는 MockMvcBuilder의 헬퍼 클래스이다.
// + MockMvcBuilder는 MockMvc를 만들어 주는 건설사이다.
// + MockMvcRequestBuilders.post로 하면 전송방식을 post라고 지정해줄 수 있다.
// ===========================================================================
// ===========================================================================
// + 단계별로 연습 :
// 1 단계 : 스프링 Beans Container의 주소로 얻은 MockMvcBuilder의 정적메소드로 'MockMvcBuilder' 객체 획득
MockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
// 2 단계 : 'MockMvcBuilder' 객체로부터 build해서, 지금 반드시 필요한 핵심객체인 'MockMvc' 객체를 획득
MockMvc mock = builder.build();
// 3 단계 : 실제 'MockMvc' 객체로 요청( request )을 만들어내려면, 'RequestBuilder' 객체가 우선 필요하다.
// + 'MockMvcRequestBuilders' Helper Class의 메소드를 이용하여 'RequestBuilder' 객체 획득
// + ( 전송방식 : GET , Request Mapping URI : /board/list인 요청을 만들어내는 RequestBuilder 객체 획득 )
MockHttpServletRequestBuilder builder2 = MockMvcRequestBuilders.get("/board/list");
// 4 단계 : 위 2단계에서 얻어낸 'MockMvc' 객체와 3단계에서 얻어낸 'RequestBuilder'객체, 2개를 이용하여 실제 요청 전송
ResultActions resultActions = mock.perform(builder2);
// 5 단계 : 호출된 Controller의 Handler 메소드에서 반환된 2개의 데이터 ( 뷰이름 + Model )를 추출
// + Controller Handler 메소드가 실행종료되어 2개의 데이터를 반환할 때까지 기다린다.
MvcResult mvcResult = resultActions.andReturn();
// 6 단계 : 'MvcResult'가 가지고 있는 2가지 데이터를 한꺼번에 'ModelAndView' 객체로 얻어냄
ModelAndView resultData = mvcResult.getModelAndView();
// 7 단계 : 'ModelAndView'에서 각각 'Model'과 'View' 객체를 얻어낼 수 있다.
String viewName = resultData.getViewName();
ModelMap model = resultData.getModelMap();
HttpStatus statusCode = resultData.getStatus();
// 8 단계 : 확인하기 ( 상태 코드는 아직 지정해주지 않았기에 null이다. )
log.info("\t + viewName : {}", viewName); // + viewName : board/list
log.info("\t + model : {}", model); // + model : {__LIST__=[BoardVO(....)]}
log.info("\t + statusCode : {}", statusCode); // + statusCode : null
// ===========================================================================
// + 축약형 ( 메소드 체이닝 ) (******)
MockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(ctx);
MockMvc mockMvc = mockMvcBuilder.build();
// + 요청 ( 전송방식 : GET , Request Mapping URI : /board/list )
RequestBuilder reqBuilder = MockMvcRequestBuilders.get("/board/list");
// + ModalMap의 실제 타입 => LinkedHashMap<String, ArrayList> (****)
ModelMap modelMap = mockMvc.
perform(reqBuilder). // + 요청을 보내고
andReturn(). // + 리턴을 기다리겠다. ( MvcResult )
getModelAndView(). // + 모델과 뷰를 얻어내겠다. ( ModelAndView )
getModelMap(); // + 그 중에서 모델만 달라 ( ModelMap )
// -------------------------------------------------------------------------------------------
modelMap.forEach((t, u) -> {
log.info("\t + t : {}", t);
log.info("\t + u : {}", u);
}); // forEach
// + 자원 해제 : Map Clear + Map객체 저장 참조변수 값을 null로 지정 -> 빠른 GC가 가능
modelMap.clear();
modelMap = null;
} // testList
// ===========================================================================
} // end class
[ 2. MockMvc 적용 - VO객체를 DTO로 변경 ] (****)
[ 2 - 1. Controller 생성 ]
더보기
[ + 코드 보기 ]
package org.zerock.myapp.controller;
import java.util.List;
import java.util.Objects;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.myapp.domain.BoardDTO;
import org.zerock.myapp.domain.BoardVO;
import org.zerock.myapp.exception.ControllerException;
import org.zerock.myapp.service.BoardService;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
@Controller
@RequestMapping("/board/*") // 기본 URI
public class BoardController implements InitializingBean {
// + Bean 의존성 주입
// + 자동 의존성 주입 발생 : (1) 주입받을 필드가 1개 (2) 이 필드를 매개변수로 가지는 생성자
// + 위와 같은 상황일 때에는 따로 주입 시그널을 보내지 않아도 자동으로 주입된다.
@Setter(onMethod_= {@Autowired})
private BoardService boardService;
// ===============================================
// + 1. 게시판 목록조회 요청 처리 핸들러 메소드
// ===============================================
// @ResponseStatus(code = HttpStatus.OK) : 컨트롤러 메소드 테스트 수행시 오류를 발생시킬 수 있다.
@GetMapping("/list") // 상세 URI
public void list (Model model) throws ControllerException {
log.info("list({}) invoked.", model);
try {
// + 목록 조회하는 service
List<BoardVO> list = this.boardService.getAllList();
// + 아래와 같은 방법 외에도 model이 아닌 Map으로 받아서,
// + model에 저장하는 것이 아니라 Map에 저장하는 방법도 있다.
// Map<String, Object> map = new HashMap<>();
// map.put("__LIST__", list);
// + 리스트가 비어있지 않을 때 model로 바인딩
if ( list != null ) {
model.addAttribute("__LIST__",list);
// + model은 Request Scope에 저장하게 되는데,
// + 이때 공유 영역에서는 NULL을 저장하지 않는다.
// + 그렇기에 이 경우 사실 if문은 필요 없다.
list.forEach(log::info);
} // if
} catch(Exception e) {
throw new ControllerException(e);
} // try - catch : ServiceException을 ControllerException으로
} // list
// ===============================================
// + 2. 새로운 게시물 등록 처리 요청 메소드 (***)
// ===============================================
// + 단순 View 호출은 GET방식,
// + 비지니스 처리를 하기 위해서는 Post로 해야 한다.
// ===============================================
// + 전송파라미터를 객체로 얻어내면, Spring에서 이것을 Command Object라고 부르며
// + Model을 사용하지 않아도 자동으로 View까지 전송된다. (***)
// ===============================================
@PostMapping("/register")
public String register (BoardDTO dto, RedirectAttributes rttrs) throws ControllerException {
log.trace("\t register({}, {}) invoked.", dto, rttrs);
try {
// + 필드에 주입받은 서비스 객체의 메소드 호출 -> 핵심 메소드 호출
if ( this.boardService.add(dto) == 1 ) {
rttrs.addAttribute("__RESULT__", "success");
} else {
rttrs.addAttribute("__RESULT__", "failed");
} // if - else
// + 업데이트 한 후에는 전체 목록 조회 페이지로 이동해야 한다. (***)
return "redirect:/board/list";
} catch(Exception e) {
throw new ControllerException (e);
} // try - catch
} // register
// ===============================================
@PostMapping("/register2")
public String register2 (BoardDTO dto, RedirectAttributes rttrs) throws ControllerException {
log.trace("\t register2({}, {}) invoked.", dto, rttrs);
try {
// + 필드에 주입받은 서비스 객체의 메소드 호출 -> 핵심 메소드 호출
if ( this.boardService.addAuto(dto) ) {
rttrs.addAttribute("__RESULT__", "success");
// rttrs.addFlashAttribute("__RESULT__", "success");
// + addFlashAttribute도 Request Scope을 통해 전달은 가능하지만, 추천하지는 x
} else {
rttrs.addAttribute("__RESULT__", "failed");
} // if - else
// + 업데이트 한 후에는 전체 목록 조회 페이지로 이동해야 한다. (***)
return "redirect:/board/list";
} catch(Exception e) {
throw new ControllerException (e);
} // try - catch
} // register
// ===============================================
// + 3. 게시판에 특정 게시물 삭제 요청 메소드
// ===============================================
@PostMapping("/remove")
public String remove( BoardDTO dto, RedirectAttributes rttrs ) throws ControllerException {
log.info("remove({}, {}) invoked.", dto, rttrs );
try {
if ( this.boardService.remove(dto) == 1 ) {
rttrs.addAttribute("__RESULT__", "success");
} else {
rttrs.addAttribute("__RESULT__", "failed");
} // if - else
return "redirect:/board/list";
} catch(Exception e) {
throw new ControllerException (e);
} // try - catch
} // remove
// ===============================================
// + 4. 새로운 게시물 수정 요청 메소드
// ===============================================
@PostMapping("/update")
public String update ( BoardDTO dto, RedirectAttributes rttrs ) throws ControllerException {
log.info("update({}, {}) invoked.", dto, rttrs);
try {
if ( this.boardService.update(dto) ) {
rttrs.addAttribute("__RESULT__", "success");
} else {
rttrs.addAttribute("__RESULT__", "failed");
} // if - else
return "redirect:/board/list";
} catch (Exception e) { throw new ControllerException (e); } // try - catch
} // update
// ===============================================
// + 선처리
// ===============================================
@Override
public void afterPropertiesSet() throws Exception {
log.trace("afterPropertiesSet() invoked.");
// 필드에 의존성이 잘 주입 되었는지 확인한다.
Objects.requireNonNull(this.boardService);
log.info("\t + this.boardService : {}", this.boardService);
} // afterPropertiesSet
} // end class
[ 2 - 2. view 생성 ]
더보기
[ + 코드 보기 ]
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>View - bord/list.jsp</title>
<script>
var result = "${ param.__RESULT__ }";
console.log(`result : ${result}`);
if ( result != null && result.length > 0 ) {
alert('${ param.__RESULT__ }');
} //if
</script>
</head>
<body>
<h1>/WEB-INF/views/bord/list.jsp</h1>
<hr>
<h1> I AM bord/list!!!</h1>
<h7> ${__LIST__}</h7>
</body>
</html>
[ + Test - MockMvc ]
더보기
[ + 코드 보기 ]
package org.zerock.myapp.controller;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
// JUNIT 5
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/root-context.xml",
"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
// + Spring MVC Controller를 테스트 하기 위해서는
// + 반드시 아래의 어노테이션을 붙여야 한다.
@WebAppConfiguration // (****)
public class BoardControllerTests {
@Autowired
private WebApplicationContext ctx;
// + WebApplicationContext는 스프링 빈즈 컨테이너의 구현 객체이다. (***)
// + 컨트롤러를 테스트 하기 위해서는 스프링 빈즈 컨테이너를 주입 받아야 한다.
// ===========================================================================
@BeforeAll
public void beforeAll() {
log.trace("beforeAll() invoked.");
} // beforeAll
// ===========================================================================
// 1. 게시물 목록 전체 조회
// ===========================================================================
@Disabled
@Test
@Order(1)
@DisplayName("1.testList")
@Timeout(value=5, unit = TimeUnit.SECONDS)
public void testList() throws Exception {
log.trace("testList() invoked.");
// ===========================================================================
// + 표현계층의 사용자 정의 Controller에 대한 테스트를 수행 시, 핵심은 WAS 구동 없이 테스트 필요 :
// + (1) @WebAppConfiguration 어노테이션
// + (2) MockMVC 클래스( 가상의 웹 브라우저 ) 사용법 :
// + 가. Spring Bean Container( WebApplicationContext를 주입받아야 한다. )
// + 나. '가'의 주입받은 객체를 이용해서, MockMvcBuilder 객체를 우선 생성
// + 다. '나'의 MockMvcBuilders란 Helper Class의 정적 메소드를 이용하여, MockMvcBuilder 객체를 얻는다.
// + 라. '다'에서 얻은 MockMvcBuilder.build() 메소드를 통해 MockMvc 객체를 얻는다.
// + 마. 'MockMvcBuilders' Helper Class의 정적 메소드를 이용해서, MockMvcRequestBuilder 객체를 얻는다.
// + 바. 'MockMvc'와 '마'에서 얻어낸, 'MockMvcRequestBuilder' 2개의 객체를 가지고 실제 가상의 요청(request)을 전송
// + - MockMvc.perform(MockMvcRequestBuilder) 메소드 호출로 수행
// + - 테스트 대상인 Controller의 핸들러 메소드가 수행되면서,
// + - 그 결과로 2가지의 정보를 얻게 된다. ( 1. Model 2. 뷰이름 )
// + 사. '바'에서 얻은 2가지 정보 중 필요로 하는 정보를 얻어내서 사용
// ===========================================================================
// + MockMvcBuilders는 MockMvcBuilder의 헬퍼 클래스이다.
// + MockMvcBuilder는 MockMvc를 만들어 주는 건설사이다.
// + MockMvcRequestBuilders.post로 하면 전송방식을 post라고 지정해줄 수 있다.
// ===========================================================================
// ===========================================================================
// + 단계별로 연습 :
// 1 단계 : 스프링 Beans Container의 주소로 얻은 MockMvcBuilder의 정적메소드로 'MockMvcBuilder' 객체 획득
MockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
// 2 단계 : 'MockMvcBuilder' 객체로부터 build해서, 지금 반드시 필요한 핵심객체인 'MockMvc' 객체를 획득
MockMvc mock = builder.build();
// 3 단계 : 실제 'MockMvc' 객체로 요청( request )을 만들어내려면, 'RequestBuilder' 객체가 우선 필요하다.
// + 'MockMvcRequestBuilders' Helper Class의 메소드를 이용하여 'RequestBuilder' 객체 획득
// + ( 전송방식 : GET , Request Mapping URI : /board/list인 요청을 만들어내는 RequestBuilder 객체 획득 )
MockHttpServletRequestBuilder builder2 = MockMvcRequestBuilders.get("/board/list");
// 4 단계 : 위 2단계에서 얻어낸 'MockMvc' 객체와 3단계에서 얻어낸 'RequestBuilder'객체, 2개를 이용하여 실제 요청 전송
ResultActions resultActions = mock.perform(builder2);
// 5 단계 : 호출된 Controller의 Handler 메소드에서 반환된 2개의 데이터 ( 뷰이름 + Model )를 추출
// + Controller Handler 메소드가 실행종료되어 2개의 데이터를 반환할 때까지 기다린다.
MvcResult mvcResult = resultActions.andReturn();
// 6 단계 : 'MvcResult'가 가지고 있는 2가지 데이터를 한꺼번에 'ModelAndView' 객체로 얻어냄
ModelAndView resultData = mvcResult.getModelAndView();
// 7 단계 : 'ModelAndView'에서 각각 'Model'과 'View' 객체를 얻어낼 수 있다.
String viewName = resultData.getViewName();
ModelMap model = resultData.getModelMap();
HttpStatus statusCode = resultData.getStatus();
// 8 단계 : 확인하기 ( 상태 코드는 아직 지정해주지 않았기에 null이다. )
log.info("\t + viewName : {}", viewName); // + viewName : board/list
log.info("\t + model : {}", model); // + model : {__LIST__=[BoardVO(....)]}
log.info("\t + statusCode : {}", statusCode); // + statusCode : null
// ===========================================================================
// + 축약형 ( 메소드 체이닝 ) (******)
MockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(ctx);
MockMvc mockMvc = mockMvcBuilder.build();
// + 요청 ( 전송방식 : GET , Request Mapping URI : /board/list )
RequestBuilder reqBuilder = MockMvcRequestBuilders.get("/board/list");
// + ModalMap의 실제 타입 => LinkedHashMap<String, ArrayList> (****)
ModelMap modelMap = mockMvc.
perform(reqBuilder). // + 요청을 보내고
andReturn(). // + 리턴을 기다리겠다. ( MvcResult )
getModelAndView(). // + 모델과 뷰를 얻어내겠다. ( ModelAndView )
getModelMap(); // + 그 중에서 모델만 달라 ( ModelMap )
// -------------------------------------------------------------------------------------------
modelMap.forEach((t, u) -> {
log.info("\t + t : {}", t);
log.info("\t + u : {}", u);
}); // forEach
// + 자원 해제 : Map Clear + Map객체 저장 참조변수 값을 null로 지정 -> 빠른 GC가 가능
modelMap.clear();
modelMap = null;
} // testList
// ===========================================================================
// 2. 새로운 게시물 등록
// ===========================================================================
// @Disabled
@Test
@Order(2)
@DisplayName("2.testRegister")
@Timeout(value=5, unit = TimeUnit.SECONDS)
public void testRegister() throws Exception {
log.trace("testRegister() invoked.");
MockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
MockMvc mockMvc = builder.build();
MockHttpServletRequestBuilder reqBuilder = MockMvcRequestBuilders.post("/board/register");
// + 필요한 전송파라미터를 설정 ( Lvalue 타입으로 구현타입을 지정해야 한다. )
reqBuilder.param("bno", "54321");
reqBuilder.param("title", "TITLE_NEW!!!!!!!!");
reqBuilder.param("content", "CONTENT_NEW!!!!");
reqBuilder.param("writer", "WRITER_NEW!!!!!");
String viewName = mockMvc.perform(reqBuilder).andReturn().getModelAndView().getViewName();
log.info("\t + viewName : {}", viewName);
} // testRegister
// ===========================================================================
// 3. 게시물 삭제 하기
// ===========================================================================
// @Disabled
@Test
@Order(3)
@DisplayName("3.testDelete")
@Timeout(value=5, unit = TimeUnit.SECONDS)
public void testDelete() throws Exception {
log.trace("testDelete() invoked.");
MockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
MockMvc mockMvc = builder.build();
MockHttpServletRequestBuilder reqBuilder = MockMvcRequestBuilders.post("/board/remove");
// + 필요한 전송파라미터를 설정 ( Lvalue 타입으로 구현타입을 지정해야 한다. )
reqBuilder.param("bno", "54321");
String viewName = mockMvc.perform(reqBuilder).andReturn().getModelAndView().getViewName();
log.info("\t + viewName : {}", viewName);
} // testDelete
// ===========================================================================
// 4. 게시물 수정하기
// ===========================================================================
// @Disabled
@Test
@Order(4)
@DisplayName("4. testUpdate")
@Timeout(value = 5, unit = TimeUnit.SECONDS)
public void testUpdate() throws Exception {
log.trace("testUpdate() invoked.");
MockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
MockMvc mockMvc = builder.build();
MockHttpServletRequestBuilder reqBuilder = MockMvcRequestBuilders.patch("/board/update");
reqBuilder.param("bno", "898989");
reqBuilder.param("title", "TITLE_NEW!!!!!!!!");
reqBuilder.param("content", "CONTENT_NEW!!!!");
reqBuilder.param("writer", "WRITER_NEW!!!!!");
String viewName = mockMvc.perform(reqBuilder).andReturn().getModelAndView().getViewName();
log.info("\t + viewName : {}", viewName);
} // testUpdate
} // end class
728x90
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 120일차 - Spring ( 페이징 처리 ) (******) (0) | 2022.08.18 |
---|---|
KH 119일차 - Spring ( Oracle 힌트 / 게시판 만들기 / 페이징 처리 ) (*******) (0) | 2022.08.17 |
KH 117일차 - Spring ( 게시판 만들기 - 비지니스 / 프레젠테이션 계층 ) (*****) (0) | 2022.08.12 |
KH 116일차 - Spring ( 게시판 만들기 - 영속성 / 비지니스 계층 ) (****) (0) | 2022.08.11 |
KH 115일차 - Spring ( 게시판 만들기 ) (*****) (0) | 2022.08.10 |
댓글