Todolist 통합 TestCode 만들기

devdo·2022년 4월 29일
0

TDD

목록 보기
4/6
post-thumbnail

https://velog.io/@mooh2jj/Todolist-TestCode-만들기
이 블로그에서 JUnit5를 이용한 단위테스트를 살펴보았습니다.

이번에는 실제 상용할 DB에 연결해서 Test 작업을 하는 것은 통합 테스트 을 똑같이 Todolist 작업을 예시로 살펴보겠습니다.

Controller

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
  • @SpringBootTest : 관련된 지식은 이 블로그를 참조해주실 바랍니다.
    https://velog.io/@jwkim/spring-boot-datajpatest-springboottest
  • @AutoConfigureMockMvc : @SpringBootTest`이 설정한 모킹한 객체를 의존성주입하기 위한 설정, 테스트대상이 되는 Controller뿐만 아니라 @Service, @Repository가 붙은 객체들도 모두 메모리에 올립니다.

기존에 단위테스츠 Controller testCode에서 given() 절들을 Repository 메서드로 체인지해주면 됩니다.

통합테스트에서는 Service 인터페이스를 사용하지 않았습니다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class TodoControllerIntegrationTest {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private TodoRepository todoRepository;

    @Autowired
    private ObjectMapper mapper;

    @BeforeEach
    void setup() {
        todoRepository.deleteAll();
    }


    @Test
    void create() throws Exception {

        TodoEntity todoEntity = TodoEntity.builder()
                .title("dsgIT")
                .order(1L)
                .completed(false)
                .build();

        TodoRequest todoRequest = TodoRequest.builder()
                .title(todoEntity.getTitle())
                .order(todoEntity.getOrder())
                .completed(todoEntity.getCompleted())
                .build();

        mvc.perform(post("/todo")
                .contentType(MediaType.APPLICATION_JSON)
                .content(mapper.writeValueAsString(todoRequest)))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.title").value(todoEntity.getTitle()))
                .andExpect(jsonPath("$.order").value(todoEntity.getOrder()))
                .andExpect(jsonPath("$.completed").value(todoEntity.getCompleted()))
                .andDo(print());

    }

    @Test
    void readOne() throws Exception {

        TodoEntity todoEntity = TodoEntity.builder()
                .title("dsgIT")
                .order(1L)
                .completed(false)
                .build();

        todoRepository.save(todoEntity);

        mvc.perform(get("/todo/{id}", todoEntity.getId()))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.id").value(todoEntity.getId()))
                .andExpect(jsonPath("$.title").value(todoEntity.getTitle()))
                .andExpect(jsonPath("$.order").value(todoEntity.getOrder()))
                .andExpect(jsonPath("$.completed").value(todoEntity.getCompleted()));
    }

    @Test
    void readOneException() throws Exception {

        Long todoId = 100L;
        TodoEntity todoEntity = TodoEntity.builder()
                .title("dsgIT")
                .order(1L)
                .completed(false)
                .build();

        todoRepository.save(todoEntity);

        mvc.perform(get("/todo/{id}", todoId))
                .andExpect(status().isNotFound());
    }

    @Test
    void readAll() throws Exception {
        int expectedLength = 10;

        IntStream.rangeClosed(1,expectedLength).forEach(i -> {
            TodoEntity todoEntity = TodoEntity.builder()
                    .title("todo_dsg"+"_"+i)
                    .order((long) i)
                    .completed(true)
                    .build();
            todoRepository.save(todoEntity);
        });

        mvc.perform(get("/todo"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.size()").value(expectedLength));
    }

    @Test
    public void updateById() throws Exception {

        TodoEntity todoEntity = TodoEntity.builder()
                .title("dsgIT")
                .order(1L)
                .completed(false)
                .build();
        TodoEntity savedTodo = todoRepository.save(todoEntity);

        mvc.perform(put("/todo/{id}", savedTodo.getId())
                        .contentType(MediaType.APPLICATION_JSON))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.title", CoreMatchers.is(savedTodo.getTitle())))
                .andExpect(jsonPath("$.order", CoreMatchers.is(1)))     // 1L이라 오류날수 있어 value 1 넣음
                .andExpect(jsonPath("$.completed", CoreMatchers.is(true)));

    }

    @Test
    public void deleteById() throws Exception {
        TodoEntity todoEntity = TodoEntity.builder()
                .title("dsgIT")
                .order(1L)
                .completed(false)
                .build();

        TodoEntity savedTodo = todoRepository.save(todoEntity);

        mvc.perform(delete("/todo/{id}", savedTodo.getId()))
                .andDo(print())
                .andExpect(status().isOk());

    }

    @Test
    void deleteAll() throws Exception {

        int expectedLength = 10;
        List<TodoEntity> todos = new ArrayList<>();

        IntStream.rangeClosed(1,expectedLength).forEach(i -> {
            TodoEntity todoEntity = TodoEntity.builder()
                    .title("todo_dsg"+"_"+i)
                    .order((long) i)
                    .completed(true)
                    .build();
            todos.add(todoEntity);
        });
        List<TodoEntity> savedTodos = todoRepository.saveAll(todos);

        todoRepository.deleteAll(savedTodos);

        mvc.perform(delete("/todo"))
                .andExpect(status().isOk());
    }
}

Repository

기존에 @DataJpaTest와 함께 @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 만 추가해주면 됩니다.

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)	
// 내장형 DB는 사용하지 않는다는 설정

실제예제

@Import(JpaAuditConfig.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Rollback(value = false)
class ItemTest {

    @Autowired
    private ItemRepository itemRepository;

    @Test
    public void saveTest() {
        LongStream.rangeClosed(1, 10).forEach(i -> {

            Item item = Item.builder()
                    .id(i)
                    .name("test 상품_" + i)
                    .price(10000 + (int)i)
                    .description("test_상품_상세_설명" + i)
                    .status(ItemSellStatus.SELL)
                    .stock(100)
                    .build();
            itemRepository.save(item);
        });
    }
}

charset utf-8 변경

ALTER TABLE shop.items convert to charset UTF8;

mysql auto_increment 초기화

-- 데이터가 없는 상태에서 실행해야 
ALTER TABLE shop.items AUTO_INCREMENT=1;
SET @COUNT = 0;
UPDATE shop.items SET shop.items.item_id = @COUNT:=@COUNT+1;
profile
배운 것을 기록합니다.

0개의 댓글