[From Hello To QueryDSL] Spring Boot Test (12/12)

By | 2020년 3월 28일
Table of Content

Spring Boot Test

JUnit 4.x 기준으로 작성합니다.

개발환경

  • Spring Boot 2.1.x
  • Gradle 4.10.2
  • junit 4.12

build.gradle 수정

build.gradle

......
dependencies {
    // ......
    testCompile("org.springframework.security:spring-security-test")
    // ......
}
......

테스트용 application.properties 생성

src/test/resources/application.properties

# 빈(empty) 파일로 생성합니다.
# 파일이 비어있으면 스프링은 자동으로 h2 를 데이타베이스로 설정합니다.

파일을 생성하지 않고 @AutoConfigureTestDatabase 를 이용해 원래의 DB 를 사용할 수 있습니다.

given-when-then

테스트 방법은 given-when-then 기법을 사용합니다.

given 파트에서는 테스트를 위한 기초환경을 구성합니다.

when 에서 테스트코드를 작성하고, then 에서 테스트결과를 검증합니다.

도메인 레이어 테스트하기

src/test/java/kr/co/episode/example/domain/posts/PostsRepositoryTest.java

@RunWith(SpringRunner.class)
@DataJpaTest
// @AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
public class PostsRepositoryTest {

    @Autowired
    private PostsRepository postsRepository;

    @Test
    public void save() {

        // given
        Posts posts = Posts.builder()
                .title("title")
                .author("author")
                .content("content")
                .build();

        // when
        Long id = postsRepository.save(posts).getId();

        // then
        Optional<Posts> saved = postsRepository.findById(id);
        assertTrue(saved.isPresent());
        assertEquals(saved.get().getTitle(), "title");
        assertEquals(saved.get().getAuthor(), "author");
        assertEquals(saved.get().getContent(), "content");
    }

    @Test
    public void update() {

        // given
        Long id = saveOnePost();
        Optional<Posts> saved = postsRepository.findById(id);

        // when
        assertTrue(saved.isPresent());
        saved.get().update("title2", "content2");
        Optional<Posts> updated = postsRepository.findById(id);

        // then
        assertTrue(updated.isPresent());
        assertEquals(updated.get().getTitle(), "title2");
        assertEquals(updated.get().getContent(), "content2");
    }

    @Test
    public void findById() {

        // given
        Long id = saveOnePost();

        // when
        Optional<Posts> saved = postsRepository.findById(id);

        // then
        assertTrue(saved.isPresent());
        assertEquals(saved.get().getTitle(), "title");
        assertEquals(saved.get().getAuthor(), "author");
        assertEquals(saved.get().getContent(), "content");
    }

    @Test
    public void delete() {

        // given
        Long id = saveOnePost();

        // when
        postsRepository.deleteById(id);

        // then
        Optional<Posts> deleted = postsRepository.findById(id);
        assertTrue(deleted.isEmpty());
    }

    @Test
    public void findAllDesc() {

        // given
        Long id = saveOnePost();

        // when
        List<Posts> postsList = postsRepository.findAllDesc();

        // then
        assertEquals(postsList.size(), 1);
    }

    private Long saveOnePost() {
        Posts posts = Posts.builder()
                .title("title")
                .author("author")
                .content("content")
                .build();
        return postsRepository.save(posts).getId();
    }
}

src/test/java/kr/co/episode/example/domain/posts/PostsPagingRepositoryTest.java

@RunWith(SpringRunner.class)
@DataJpaTest
public class PostsPagingRepositoryTest {

    @Autowired
    private PostsRepository postsRepository;

    @Autowired
    private PostsPagingRepository postsPagingRepository;

    @Test
    public void search() {

        // given
        PostsSearchDto postsSearchDto = PostsSearchDto.builder()
                .title("title")
                .author("author")
                .orderBy(false)
                .build();

        Pageable pageable = PageRequest.of(0, 10);

        ArrayList<Posts> postsArrayList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Posts post = Posts.builder()
                    .title("title" + 1)
                    .author("author")
                    .content("content")
                    .build();

            postsRepository.save(post);
            postsArrayList.add(post);
        }

        // when
        Page<Posts> posts = postsPagingRepository.search(pageable, postsSearchDto.toEntity());

        // then
        for (int i = 0; i < 1; i++) {
            String a = posts.getContent().get(i).getTitle();
            String b = postsArrayList.get(i).getTitle();
            assertEquals(a, b);
        }
    }
}

컨트롤러 테스트하기

테스트용 application.properties 수정

실제로 접속하지는 않으므로 client-id/client-secret 은 아무 값을 입력해도 됩니다.

src/test/resources/application.properties

spring.security.oauth2.client.registration.google.client-id=aaaa
spring.security.oauth2.client.registration.google.client-secret=bbbb
spring.security.oauth2.client.registration.google.scope=profile,email

API 컨트롤러 테스트하기

실제로 RestController 를 랜덤포트로 실행하고, @WithMockUser(roles="USER") 를 이용해 권한을 부여합니다.

src/test/java/kr/co/episode/example/web/PostsApiControllerTest.java

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PostsApiControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private PostsRepository postsRepository;

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup() {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
    }

    @After
    public void tearDown() throws Exception {
        postsRepository.deleteAll();
    }

    @Test
    @WithMockUser(roles="USER")
    public void save() throws Exception {

        // given
        String title = "title";
        String content = "content";
        String author = "author";
        PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder()
                .title(title)
                .content(content)
                .author(author)
                .build();

        String url = "http://localhost:" + port + "/api/v1/posts";

        // when
        // org.springframework.test.web.servlet 을 임포트합니다.
        mvc.perform(post(url)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(new ObjectMapper().writeValueAsString(requestDto)))
                .andExpect(status().isOk());

        // then
        List<Posts> all = postsRepository.findAll();
        // org.assertj.core.api.Assertions 을 임포트합니다.
        assertThat(all.get(0).getTitle()).isEqualTo(title);
        assertThat(all.get(0).getContent()).isEqualTo(content);
    }

    @Test
    @WithMockUser(roles="USER")
    public void update() 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";

        PostsUpdateRequestDto requestDto = PostsUpdateRequestDto.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();
        assertThat(all.get(0).getTitle()).isEqualTo(expectedTitle);
        assertThat(all.get(0).getContent()).isEqualTo(expectedContent);
    }
}

컨트롤러 테스트하기

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class IndexControllerTest {

    @Autowired
    private PostsRepository postsRepository;

    @Autowired
    private TestRestTemplate restTemplate;

    @Before
    public void setUp() throws Exception {
        postsRepository.save(Posts.builder()
                .title("title title title")
                .content("content content content")
                .author("author author author")
                .build());
    }

    @After
    public void tearDown() throws Exception {
        postsRepository.deleteAll();
    }

    @Test
    public void index() {

        // given

        // when
        String body = this.restTemplate.getForObject("/", String.class);

        // then
        // org.assertj.core.api.Assertions 을 임포트합니다.
        // org.junit.Assert 가 임포트되어 있으면 제거합니다.
        assertThat(body).contains("title title title");
    }
}

답글 남기기