2022_02_27 - oneso123456789/2022 GitHub Wiki

other

testRegister() 도중 bno 즉 시퀀스가 1이 아니라 10 20 증가할때가 있는것을 확인함
이 문제는 oracle sequence 속도 상승을 위해 여러개의 시퀀스 값을 캐시에 올려놓고
작업하기 때문임 해결 방법은 alter sequence 시퀀스 이름 nocache; 를해주면됨
나는 sqldeveloper를 이용해서 alter sequence seq_board nocache;를 해줌
참고 사이트 :https://m.blog.naver.com/opgj123/221322082219
더 사용해보고 또 이런 문제가 생기면 다른 방식으로 해결해봐야겠음

10.2 BoardController의 작성

BoardController는 com.crow.controller 패키지에 선언하고 URL 분석된 내용들을 반영하는 메서드를 설계함

com.crow.controller.BoardController 클래스

package com.crow.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
public class BoardController {

}

BoardController는 @Controller 어노테이션을 추가해서 스프링의 빈으로 인식할 수 있게 하고,
@RequestMapping을 통해서 '/board'로 시작하는 모든 처리를 BoardController가 하도록 지정함
BoardController가 속한 com.crow.controller 패키지는 servlet-context.xml에 기본으로 설정되어
있으므로 별도의 설정이 필요하지 않음
(Java 설정을 이용하는 경우에는 @ComponentScan을 이용하면됨)

10.2.1 목록에 대한 처리와 테스트

BoardController에서 전체 목록을 가져오는 처리를 먼저 작성함
BoardController는 BoardService 타입의 객체와 같이 연동해야 하므로 의존성에 대한 처리도 같이 진행함

com.crow.controller.BoardController 클래스

package com.crow.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.crow.service.BoardService;

import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {

    private BoardService service;

    @GetMapping("/list")
    public void list(Model model) {

        log.info("list");
        model.addAttribute("list", service.getList());

    }
}

BoardController는 BoardService에 대해서 의존적이므로 @AllArgsConstructor를 이용해서
생성자를 만들고 자동으로 주입해줌
(만일 생성자를 만들지 않을 경우에는 @Setter(onMethod_ = { @Autowired })를 이용해서 처리함)

  • @AllArgsConstructor: 모든 필드 값을 파라미터로 받는 생성자를 만듦
  • @NoArgsConstructor: 파라미터가 없는 기본 생성자를 생성
  • @RequiredArgsConstructor: final이나 @NonNull인 필드 값만 파라미터로 받는 생성자 만듦

list()는 나중에 게시물의 목록을 전달해야 하므로 Model을 파라미터로 지정하고,
이를 통해서 BoardServiceImpl 객체의 getList() 결과를 담아 전달함(addAttribute)
BoardController 테스트는 스프링의 테스트 기능을 통해서 확인해 볼 수있음

src/test/java에 com.crow.controller패키지에 BoardControllerTests 클래스를 선언함

WAS 없이 코드 테스트

이번 테스트 코드는 기존과 좀 다르게 진행되는데 그 이유는 웹을 개발할 때 매번 URL을 테스트 하기 위해서
Tomcat과 같은 WAS를 실행하는 불편한 단계를 생략하기 위해서임
스프링의 테스트 기능을 활용하여 개발 당시에 Tomcat(WAS)을 실행하지 않고도 스프링과 웹 URL을 테스트가능

WAS를 실행하지 않기 위해서는 약간의 추가적인 코드가 필요하지만 반복적으로 서버를 실행하고,
화면에 입력하고, 오류를 수정하는 단계를 줄여줄 수 있기 때문에 Controller를 테스트 할 때는
한번씩 고려해 볼 만한 방법임

src/test/java 밑의 com.crow.controller.BoardControllerTests 클래스

package com.crow.controller;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
//Test for Controller
@WebAppConfiguration
@ContextConfiguration({
    "file:src/main/webapp/WEB-INF/spring/root-context.xml",
        "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" })
@Log4j
public class BoardControllerTests {

    @Setter(onMethod_ = { @Autowired })
    private WebApplicationContext ctx;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
    }

    @Test
    public void testList() throws Exception {

        log.info(
                mockMvc.perform(MockMvcRequestBuilders.get("/board/list"))
                .andReturn()
                .getModelAndView()
                .getModelMap());
    }
}

테스트 클래스의 선언부에는 @WebAppConfiguration 어노테이션을 적용함 @WebAppConfiguration은 Servley의 ServletContext를 이용하기 위해서 인데,
스프링에서는 WebApplicationContext라는 존재를 이용하기 위해서임

@Before 어노테이션이 적용된 setup()에서는 import 할 때 JUnit을 이용해야함
@Before가 적용된 메서드는 모든 테스트 전에 매번 실행되는 메서드임

MockMVC는 말 그대로 '가짜 mvc'라고 생각하면 됨
가짜로 URL과 파라미터 등을 브라우저에서 사용하는 것처럼 만들어서 Controller를 실행해 볼 수 있음
testList()는 MockMvcRequestBuilders라는 존재를 이용해서 GET 방식을의 호출을 함
이후에는 BoardController의 getList()에서 반환된 결과를 이용해서 Model에 어떤 데이터들이
담겨 있는지 확인함
Tomcat을 통해서 실행되는 방식이 아니므로 기존의 테스트 코드를 실행하는 것과 동일하게 실행함

TestList()를 실행한 결과는 데이터베이스에 저장된 게시물들을 볼 수 있음

10.2.2 등록처리와 테스트

BoardController에 POST 방식으로 처리되는 register()를 작성하면 다음과 같음

BoardController 클래스의 일부

    @PostMapping("/register")
    public String register(BoardVO board, RedirectAttributes rttr) {

        log.info("controller register: " + board);
        
        service.register(board);
        
        rttr.addFlashAttribute("result", board.getBno());
        
        return "redirect:/board/list";

    }

register() 메서드는 조금 다르게 string을 리턴 타입으로 지정하고, RedirectAttributes를 이용함
리턴 시에는 'redirect:' 접두어를 사용하는데 이를 이용하면 스프링 MVC가 내부적으로
response.sendRedirect를 처리해 주기 때문에 편리함

테스트 코드는 아래와 같이 작성함

com.crow.controller.BoardControllerTests 클래스의 일부

    @Test
    public void testRegister() throws Exception{
        
        String resultPage = mockMvc.perform(MockMvcRequestBuilders.post("/board/register")
                .param("title", "BoardControllerTests 제목")
                .param("content","BoardControllerTests 내용" )
                .param("writer", "BoardControllerTests 작성자")
                ).andReturn().getModelAndView().getViewName();
        
        log.info(resultPage);
    }

테스트 할 때 MockMvcRequestBuilder의 post()를 이용하면 POST 방식으로 데이터를 전달할 수 있고,
Param()을 이용해서 전달해야 하는 파라미터들을 지정할 수 있음
( 태그와 유사한 역할)
이러한 방식으로 코드를 작성하면 최초 작성 시에는 일이 많다고 느껴지지만 매번 입력할 필요가
없기 때문에 오류가 발생하거나 수정하는 경우 반복적인 테스트가 수월해짐

테스트 코드 실행 로그를 보면 상단에 BoardVO객체로 올바르게 데이터가
바인딩된 결과를 볼 수 있고, 중간에는 SQL의 실행결과가 보임
마지막에는 최종 반환 문자열을 확인할 수 있음
BoardController redirect:/board/list

testRegister() 작성중 오류

String resultPage = mockMvc.perform(MockMvcRequestBuilders.post("/board/register")를 post("/board/regiser")로 매핑을 잘못 작성함 이런 ide 디버거에 잡히지 않는 구문 오류를 조심해야함

10.2.3 조회 처리와 테스트

⚠️ **GitHub.com Fallback** ⚠️