inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)

테스트 시행 시 롤백

507

enimbe99

작성한 질문수 5

0

게시글 조회5-페이징처리(QueryDSL) 강의 내용 이후 전체 테스트를 시행하면 PostControllerTest에서 test5, test6에서 id값을 검증할때에 이전의 테스트에서 PostRepository에 저장이 되어 test5에서는 id값이 30이어야하는데 33이고, test6에서는 30이어야하는데 63으로 이전 테스트 수행 결과가 롤백되지 않아요.

BeforeEach랑 Transactional 둘 다 사용해보았는데 테스트가 독립적으로 수행되지 않습니다.

찾아보니 sequence는 롤백되지 않는 것이 DB의 기본 규칙이라는데 호돌맨님은 강의에서 전체 테스트를 수행하여도 모든 테스트케이스가 통과되어서 코드에서 어떤 부분이 다른지 궁금합니다.

package com.blog.controller;

import com.blog.domain.Post;
import com.blog.repository.PostRepository;
import com.blog.request.PostCreate;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
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.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class PostControllerTest {

    // TODO ObjectMapper 공부하기
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private PostRepository postRepository;

    @Test
    @DisplayName("/posts 요청 시 출력한다.")
    void test() throws Exception {
        // given
        PostCreate request = PostCreate.builder()
                .title("제목입니다.")
                .content("내용입니다.")
                .build();

        String json = objectMapper.writeValueAsString(request);

        // expected
        mockMvc.perform(post("/posts")
                        .contentType(APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isOk())
                .andDo(print());
    }

    @Test
    @DisplayName("/posts 요청 시 title 값은 필수다.")
    void test2() throws Exception {
        // given
        PostCreate request = PostCreate.builder()
                .content("내용입니다.")
                .build();

        String json = objectMapper.writeValueAsString(request);

        // expected
        mockMvc.perform(post("/posts")
                        .contentType(APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.code").value("400"))
                .andExpect(jsonPath("$.message").value("잘못된 요청입니다."))
                .andExpect(jsonPath("$.validation.title").value("타이틀을 입력해주세요."))
                .andDo(print());
    }

    @Test
    @DisplayName("/posts 요청 시 DB에 값이 저장된다.")
    void test3() throws Exception {
        // given
        PostCreate request = PostCreate.builder()
                .title("제목입니다.")
                .content("내용입니다.")
                .build();

        String json = objectMapper.writeValueAsString(request);

        // when
        mockMvc.perform(post("/posts")
                        .contentType(APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isOk())
                .andDo(print());

        // then
        assertEquals(1L, postRepository.count());

        Post post = postRepository.findAll().get(0);
        assertEquals("제목입니다.", post.getTitle());
        assertEquals("내용입니다.", post.getContent());
    }

    @Test
    @DisplayName("글 1개 조회")
    void test4() throws Exception {
        // given
        Post post = Post.builder()
                .title("123456789012345")
                .content("bar")
                .build();
        postRepository.save(post);

        // expected
        mockMvc.perform(get("/posts/{postId}", post.getId())
                        .contentType(APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(post.getId()))
                .andExpect(jsonPath("$.title").value("1234567890"))
                .andExpect(jsonPath("$.content").value("bar"))
                .andDo(print());
    }

    @Test
    @DisplayName("글 여러개 조회")
    void test5() throws Exception {
        // given
        List<Post> requestPosts = IntStream.range(1, 31)
                .mapToObj(i -> Post.builder()
                        .title("호돌맨 제목 " + i)
                        .content("반포자이 " + i)
                        .build())
                .collect(Collectors.toList());
        postRepository.saveAll(requestPosts);

        // expected
        mockMvc.perform(get("/posts?page=1&size=10")
                        .contentType(APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.length()", is(10)))
//                .andExpect(jsonPath("$[0].id").value(30)) // sequence는 롤백되지 않음(DB 기본규칙) - mysql 계열이라면 auto_increment로 생성한 값은 commit, rollback 에 상관없이 한번 생성한 값을 그대로 유지합니다.
                .andExpect(jsonPath("$[0].title").value("호돌맨 제목 30"))
                .andExpect(jsonPath("$[0].content").value("반포자이 30"))
                .andDo(print());
    }

    @Test
    @DisplayName("페이지를 0으로 요청하면 첫 페이지를 가져온다")
    void test6() throws Exception {
        // given
        List<Post> requestPosts = IntStream.range(1, 31)
                .mapToObj(i -> Post.builder()
                        .title("호돌맨 제목 " + i)
                        .content("반포자이 " + i)
                        .build())
                .collect(Collectors.toList());
        postRepository.saveAll(requestPosts);

        // expected
        mockMvc.perform(get("/posts?page=0&size=10")
                        .contentType(APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.length()", is(10)))
//                .andExpect(jsonPath("$[0].id").value(30))
                .andExpect(jsonPath("$[0].title").value("호돌맨 제목 30"))
                .andExpect(jsonPath("$[0].content").value("반포자이 30"))
                .andDo(print());
    }

}

vue.js aws spring-boot jpa spring-security

답변 2

1

luxleo

안녕하세요
혹시 데이터베이스 임베디드 모드로 설정하셨나요?
메모리에 디비 올라오면, 스프링 리로드 할때마다 초기화 한다고
들었습니다. 그러면 시퀀스 Pk도 초기화 되지 않을까 생각합니다.

0

호돌맨

안녕하세요.
호돌맨입니다.

저는 직접 기대 값을 넣지 않았습니다.

image
위와 같이 저장한 post의 id를 가져오도록 했습니다.

감사합니다.

Deprecated 관련 사항들

0

104

2

깃헙 collaboator 초대 관련

0

89

1

강의 듣다가 도커 이미지 생성시 각각도 가능하나 그렇게 사용하는데가 많은지 모르겠다라는 말을 듣고 남김니다

0

157

2

logout 후에 login 페이지 이동은 어디서 시켜주는건가요?

0

233

1

다중 데이터를 삭제 할 때

0

271

2

querydsl Q class 이슈

0

415

2

Windows WSL Vue 설정

2

247

1

Dip, @transactional

0

189

1

[vite] http proxy error: /auth/login

0

1045

2

로그인 하고 나서 GET요청으로 메인페이지 요청

0

234

2

GitHub Collaborator 초대 관련

0

258

2

Window에서 Vue.js 설정

0

321

2

(솔루션 수정)'tsyringe' Error: TypeInfo not known for "클래스명"

0

713

2

collaboator로 초대받을 수 있을까요??

0

283

2

SecurityMockContext 로부터 유저 정보를 가져오기

0

262

1

given 부분이 길어질 때 어떻게 처리하면 좋을까요?

0

318

1

섹션9 프론트의 코드를 보고싶습니다,,,

0

423

1

Spring Security - defaultSuccessUrl 질문

0

627

1

강의 화면이 나오지 않습니다. 음성과 자막만 나와요

0

302

1

JPAQueryFactory(em)의 객체 생성자 오류에 대해서 질문이 있습니다ㅜㅜ

0

690

2

ExceptionHandler가 AccessDeniedHandler(Http403Handler)를 먹어버리는 현상

0

1182

2

섹션10 언제 나오나요?

0

485

1

CommentService에서 Repository를 호출하지 않는데도

0

343

1

Editor....를 활용한 패턴에 질문있습니다.

0

496

1