스프링

 

라이브러리  그래들

    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 선택  -> 메소드 선택

1. 간단한 junit 테스트 방법 IntelliJ

 

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로 혼자 구현하는 웹 서비스

이동욱

가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다. 경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현한다. JPA와 JUnit 테스트, 그레이들, 머스테치, 스프링 시큐리티를 활용한 소셜 로그인 등으로 애플리케이션을 개발하고, 뒤이어 AWS 인프라의 기본 사용법과 AWS EC2와 RDS를 사용...

 

about author

PHRASE

Level 60  라이트

대인(大人), 즉 도(道)를 닦은 훌륭한 자는 자기라는 것을 생각하지 않는다. -장자

댓글 ( 4)

댓글 남기기

작성

스프링 목록    more