라이브러리 그래들
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
컨트롤에서 샘플 데이터
HelloController
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name") String name,
@RequestParam("amount") int ammount
){
return new HelloResponseDto(name, ammount);
}
}
HelloResponseDto
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.io.Serializable;
@Getter
@RequiredArgsConstructor
public class HelloResponseDto implements Serializable {
private final String name;
private final int ammount;
}
PostsDto
import com.jojoIdu.book.srpingboot.domain.entity.Posts;
import lombok.*;
import java.time.LocalDateTime;
@Getter
@NoArgsConstructor
@ToString
public class PostsDto {
private Long id;
private String title;
private String content;
private String author;
private LocalDateTime modifiedDate;
public PostsDto(Posts entity){
this.id=entity.getId();
this.title=entity.getTitle();
this.content=entity.getContent();
this.author=entity.getAuthor();
this.modifiedDate=entity.getModifiedDate();
}
@Builder
public PostsDto(String title, String content, String author){
this.title=title;
this.content=content;
this.author=author;
}
public Posts toEntity() {
return Posts.builder()
.title(title)
.content(content)
.author(author)
.build();
}
}
PostsApiController
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
@RestController
@Slf4j
public class PostsApiController {
private final PostsService postsService;
@PostMapping("/api/v1/posts")
public Long save(@RequestBody PostsDto requestDto) throws Exception {
return postsService.save(requestDto);
}
@PutMapping("/api/v1/posts/{id}")
public Long update(@PathVariable Long id, @RequestBody PostsDto requestDto){
return postsService.update(id, requestDto);
}
@GetMapping("/api/v1/posts/{id}")
public PostsDto findById(@PathVariable Long id){
return postsService.findById(id);
}
@DeleteMapping("/api/v1/posts/{id}")
public Long delete(@PathVariable Long id){
postsService.delete(id);
return id;
}
}
인텔리 제이에서 테스트 클래스 생성 방법
해당 클래스 또는 메소드에서 마우스 우클릭 -> Generate -> test 선택 -> 메소드 선택
2. 이클립스에서 테스트 클래스 생성 방법
[Eclipse] 자바 JUnit 사용 방법 & 단위 테스트 방법
출처: https://junghn.tistory.com/entry/Eclipse-자바-JUnit-사용-방법-단위-테스트-방법 [코딩 시그널]
①private.MockMvc mvc
웹 API 를 테스트할 때 사용.
스프링 MVC 테스트의 시작점
이 클래스를 통해 HTTP GET, POSt 등에 대한 API 테스트를 할 수 있음.
② mvc.perform(get("/hello"))
MockMvc 를 통해/hello 주소로 HTTP GET 요청을 한다.
체이닝이 지원되어 아래와 같이 여러 검증 기능을 이어서 선언할 수 있음
③ .andExpect(status().isOk())
.mvc.perform 의 결과를 검증.
HTTP Header의 Status 를 검증.
우리가 흔히 알고 있는 200, 404, 500 등의 상태를 검증한다.
여기선 OK 즉, 200인지 아닌지를 검증
④ .andExpect(content().string(hello))
.mvc perform 의 결과를 검증
.응답 본문의 내용을 검증
.Controller 에서 "hello" 를 리턴하기 때문에 이 값이 맞는 검증
Junit5 테스트 하기
간단한 테스트일 경우
@AutoConfigureMockMvc 를 통해 Spring Boot 에서 사용되는 여러 설정(@Service 등) 을 사용하도록 선언
그러나 다음은 공통 상속 클래스 만들어서 사용하는 처리 방법
1. AbstractControllerTest
공통 상속 클래스 만들기
import org.junit.jupiter.api.BeforeEach;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.filter.CharacterEncodingFilter;
import java.nio.charset.StandardCharsets;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@SpringBootTest
public abstract class AbstractControllerTest {
protected MockMvc mockMvc;
abstract protected Object controller();
@BeforeEach
private void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(controller())
.addFilter(new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true))
.alwaysDo(print())
.build();
}
}
2. HelloControllerTest
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.http.MediaType;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import org.junit.jupiter.api.DisplayName;
public class HelloControllerTest extends AbstractControllerTest{
@Autowired
private HelloController helloController;
@Override
protected Object controller() {
return helloController;
}
@Test
@DisplayName("hello가_리턴 ---- 테스트")
void hello가_리턴된다() throws Exception {
String content = "hello";
this.mockMvc.perform(
get("/hello")
.contentType(MediaType.APPLICATION_JSON)
.content(content)
)
.andExpect(status().isOk())
.andExpect( content().string("hello"))
.andDo(print());
}
@Test
@DisplayName("helloDto가_리턴된다")
public void helloDto가_리턴된다() throws Exception{
String name="hello";
int amount =10000;
ObjectMapper objectMapper=new ObjectMapper();
HelloResponseDto dto =new HelloResponseDto(name, amount);
String expectedJson =objectMapper.writeValueAsString(dto);
this.mockMvc.perform(
get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount))
)
.andExpect(status().isOk())
.andExpect( content().string(expectedJson));
}
}
PostsApiControllerTest
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jojoIdu.book.srpingboot.domain.entity.Posts;
import com.jojoIdu.book.srpingboot.domain.repository.PostsRepository;
import com.jojoIdu.book.srpingboot.web.dto.PostsDto;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class PostsApiControllerTest extends AbstractControllerTest {
@Autowired
private PostsApiController postsApiController;
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@LocalServerPort
private int port;
@Autowired
private PostsRepository postsRepository;
//시큐리티 보안설정
@BeforeEach
public void setup(){
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
@Override
protected Object controller() {
return postsApiController;
}
/**
*
@WithMockUser(roles = "USER")
인증된 모의(가짜) 사용자를 만들어서 사용한다.
roles 에 권한을 추가할 수 있다.
즉, 어노테이션으로 인해 ROLE_USER 권한을 가진 사용자가 API를 요청하는 것과
동일한 효과를 가지게 된다.
*/
@DisplayName("posts_등록된다()")
@Test
@WithMockUser(roles = "USER")
public void posts_등록된다() throws Exception {
String title="title- 테스트";
String content="홍길동";
PostsDto requestDto=PostsDto
.builder()
.title(title)
.content(content)
.build();
System.out.println(" 등록된다.......");
String url ="http://localhost:"+port+"/api/v1/posts";
//when
mvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(new ObjectMapper().writeValueAsString(requestDto)))
.andExpect(status().isOk());
//then
List<Posts> all = postsRepository.findAll();
assertEquals(all.get(0).getTitle(),title );
assertEquals(all.get(0).getContent(),content);
}
@DisplayName("post_수정()")
@Test
@WithMockUser(roles = "USER")
public void post_수정() throws Exception{
//given
Posts savedPosts = postsRepository.save(Posts.builder()
.title("title")
.content("content")
.author("author")
.build());
Long updateId = savedPosts.getId();
String expectedTitle = "title2";
String expectedContent = "content2";
PostsDto requestDto = PostsDto.builder()
.title(expectedTitle)
.content(expectedContent)
.build();
String url = "http://localhost:" + port + "/api/v1/posts/" + updateId;
//when
mvc.perform(put(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(new ObjectMapper().writeValueAsString(requestDto)))
.andExpect(status().isOk());
//then
List<Posts> all = postsRepository.findAll();
assertEquals(all.get(0).getTitle(), expectedTitle );
assertEquals(all.get(0).getContent(),expectedContent);
}
}
소스 : https://github.com/braverokmc79/AwsAndSpringBoot
참고 :
1 )[JUnit5] MockMvc로 Spring Boot 통합 테스트하기
2) Spring Boot JUnit 5 MockMvc Test
3) Spring Boot 에서 JUnit5 , MockMvc를 이용하여 테스트 진행하기
스프링 부트와 AWS로 혼자 구현하는 웹 서비스
이동욱 저
가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다. 경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현한다. JPA와 JUnit 테스트, 그레이들, 머스테치, 스프링 시큐리티를 활용한 소셜 로그인 등으로 애플리케이션을 개발하고, 뒤이어 AWS 인프라의 기본 사용법과 AWS EC2와 RDS를 사용...

















댓글 ( 4)
댓글 남기기