JUnit을 활용해 Controller 단위테스트하기

KEH·2021년 2월 25일
1
post-thumbnail

오늘은 Junit을 활용한 컨트롤러 테스트에 대한 내용이다.
책을 보며 스프링을 공부하다 이녀석 때문에 엄청나게 고생을 했다. 나처럼 고생하는 사람들을 위해 이 글을 쓴다.


단위테스트를 하는 이유는 굳이 **서버를 실행시키고, 테스트하고 싶은 페이지까지 이동해서 테스트를 해야 하는 번거로움을 덜고자** 실행된다.

우선 내 프로젝트의 버전은 아래와 같다.(pom.xml)

<properties>
	<java-version>1.8</java-version>
	<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
	<org.aspectj-version>1.6.10</org.aspectj-version>
	<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>

단위테스트를 위해서 아래와 같이 두 개의 라이브러리가 필요하다.

spring-test
junit

<dependency>  
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>  
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>${org.springframework-version}</version>
</dependency>

이때 spring-test 라이브러리의 버전은 spring 버전과 같은 버전으로 맞춰야 한다!!

그리고 한 가지 중요한 것이 또 있다.

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>servlet-api</artifactId>
	<version>2.5</version>
	<scope>provided</scope>
</dependency>

아마 프로젝트를 생성하면 pom.xml에 servlet-api 라이브러리가 위와 같이 돼 있을 것이다. 하지만 현재 나와 같은 spring 버전을 사용한다면

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>4.0.0</version>
	<scope>provided</scope>
</dependency>
<!-- <dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>servlet-api</artifactId>
	<version>2.5</version>
	<scope>provided</scope>
</dependency> -->

주석처리나 해당 코드를 삭제한 후 위와 같이 변경해줘야 한다.

GET 전송 테스트하기

가장 먼저 GET 방식으로 전송할 때 컨트롤러의 단위테스트를 진행해 볼 것이다. 디렉토리 구조와 컨트롤러 클래스의 코드는 다음과 같다.

package com.bookBoard.controller;

@Log4j
@Controller
@RequestMapping("/board/*")
public class BoardController {
	@Setter(onMethod_ = {@Autowired})
	private BoardService bService;
	
	@GetMapping("/list")
	public void list() {
		log.info("list .................");
		List<BoardVO> board = bService.getBoardList();
		log.info(board);
	}
}

위의 코드를 서버실행 없이 단위테스트를 통해 잘 실행되는지 확인해 볼 것이다. 디렉토리 구조는 다음과 같다.

package com.bookBoard.controller;

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@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() {
		mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
		log.info("complete setup!");
	}
	
	@Test
	public void testList() throws Exception {
		mockMvc.perform(get("/board/list"));
	}
}
  1. @WebAppConfiguration : 자동으로 Web과 컨트롤러에서 사용되는 Bean들을 생성하여 등록함.
  2. @RunWith(SpringJUnit4ClassRunner.class) : test 시 junit을 사용한다는 의미의 어노테이션.
  3. @ContextConfiguration
  • 해당 어노테이션을 이용해 web과 컨트롤러에 등록돼 있는 Bean이 어떤 것들인지 알 수 있음.
  • @WebAppConfiguration은 컨트롤러에 @Autowired와 같은 어노테이션이 붙어있는 것들 중 @ContextConfiguration에 등록돼 있는 xml 파일에 존재하는 Bean들만 자동으로 생성하고 등록한다.
  1. @Before : 모든 테스트 메서드가 실행되기 전 실행되는 메서드를 표시할 때 사용하는 어노테이션.
  2. MockMvc : 가짜 MVC. 가짜로 URL과 파라미터를 브라우저에서 사용하는 것처럼 만들어서 Controller를 실행할 수 있음.
  3. @Before 어노테이션이 적혀 있는 메서드에서는 정확히는 모르겠지만 브라우저를 실행하기 전 root-context와 servlet-context에 존재하는 빈들을 확인하는 등 먼저 해당 웹의 설정을 미리 하는 것 같다.
  4. testList() 메서드를 통해 BoardController의 "/board/list" URI를 테스트할 수 있다.
  5. mockMvc의 perform() : 해당 URI로 요청을 전송함.



POST 전송 테스트하기

POST 전송의 컨트롤러 코드이다.

package com.bookBoard.controller;

@Log4j
@Controller
@RequestMapping("/board/*")
public class BoardController {
	@Setter(onMethod_ = {@Autowired})
	private BoardService bService;
    
   	@PostMapping("/remove")
	public String remove(String bno) {
		log.info("remove ...............................");
		log.info("delete result : " + bService.deleteBoard(bno));
		
		return "";
	}
}

POST 전송 테스트 코드이다.

package com.bookBoard.controller;

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@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() {
		mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
		log.info("complete setup!");
	}
    
  	@Test
	public void testRemove() throws Exception {
		mockMvc.perform(post("/board/remove")
     		.param("bno", "bord0021"));
	}
}

testRemove() 메서드에서 get방식에서는 perform() 안에 get()을 사용했지만 지금은 post 방식을 테스트하기 때문에 post()를 사용한다. 또 해당 방식에선 bno라는 파라미터가 필요한데 이를 위해 param이란 메서드를 사용하여 해당 파라미터의 값을 적어주면 된다.


아직 junit을 10분의 1도 안써봤지만 우선 써 본거에 만족중이다 :) 계속 공부하면서 junit의 많은 기능을 써 봐야겠다!

참고

참고1
코드로 배우는 스프링 웹 프로젝트

profile
개발을 즐기고 잘하고 싶은 안드로이드 개발자입니다 :P

0개의 댓글