스파르타 spring 2기 TIL day18

fart man·2026년 1월 2일

간단한 TODO app 테스팅하기 (그리고 그에 따른 고통)

Sparta과제로 Spring을 이용해 todo app을 만들게 되었다. 간단해 보이기에 여러 추가 목표를 스스로 만들었고 그리고 그 대부분을 실패했다 :D

그 추가적인 목표중 하나는 testing이었다.

나의 순진무구한 생각은 이랬다.

그냥 server에 요청 보낸다음 받은 기록을 적고 그거 맞는지 본담에 저장하고 나중에 비교하면 되는거 아닌가?

그리고 인터넷을 뒤져보니 이를 위한 approvaltests란 라이브러리도 있길래 딱이다 싶어서 시도를 했다. 그리고 고통이 시작됬다.

고통1 : 무엇을 기록할까?

코드를 짜고나니 나름 잘 동작하는듯 보였다

POST /api/todos

== REQUEST ==

{
  "password" : "69420",

  "todoAuthor" : "momo",
  "todoTitle" : "산책하러가기",
  "todoBody" : "밖에 산책 하러 가기",
  "todoDate" : "2000-01-22T00:00:00.0000000"
}

== RESPONSE ==

status code : 201 CREATED

{
  "todoId" : 1,
  "todoAuthor" : "momo",
  "todoTitle" : "산책하러가기",
  "todoBody" : "밖에 산책 하러 가기",
  "todoDate": "2000-01-22T00:00:00.0000000",
  "createdAt": "2026-01-02T10:47:00.16411",
  "modifiedAt": "2026-01-02T10:47:00.16411"
}

하지만 위 기록을 담 테스트를 돌린 기록과 비교 할때 문제가 생긴다.

일단 시간이 다르다. (시간이 지났으니까)

그리고 todoId도 같을 거라는 보장이 없다. (아니, 같아야 된다는 조건이 테스트에 있어서는 안된다).

그래서 위 필드 이름을 다른 필드로 교체하는 코드를 작성하였다.

    helper.addFieldsToReplace("1111-02-03T04:05:06.777777", "createdAt", "modifiedAt", "todoId");

    // spring 기본 에러 timestamp 제거
    helper.addFieldsToReplace("1111-02-03T04:05:06.666Z", "timestamp");
    helper.addFieldsToReplace("{todoId}", "todoId");
    // spring 기본 에러 path 제거
    helper.addFieldsToReplace("{requestPath}", "path");

하지만 이런 코드를 적다보면서 느끼게 된 점은 없애야 할 필드를 적는게 아니고 체크해야할 필드를 적어야 한다는 것이다. 예상치 못하게 실행마다 달라지는 값들이 일일이 적기에는 너무 많다.

고통2 : 테스트 케이스마다 DB 초기화하기.

무슨 고집인지 모르겠지만 나는 @SpringBootTest(webEnvironment = WebEnvironment.MOCK)일 경우 에러가 json형태로 오는 것이 아닌 java exception형태로 들어오는게 싫어서 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)을 쓰기고 하였다.

하지만 그렇게 되면 @Transactional이 동작을 안하게 된다. server와 client가 별도의 Thread에서 돌기 때문이다.

그래서 첨에는 @DirtiesContext를 이용해 DB를 초기화하였다.

자동은 잘하나...

너무 느리다

정말 창피할정도로 느려서 다른 방법을 찾아보니 두가지 조언이 있었다.

  1. 어차피 실서버는 더러우니 그냥 DB가 초기화가 안될거란 가정하에 테스트를 작성하라
  2. DB초기화 하는 코드를 직접 짜라.

나는 2번을 선택하기로 했다.

  @AfterEach
  void cleanupDb(@Autowired JdbcTemplate template) {
    JdbcTestUtils.deleteFromTables(template, "todos");
  }

이 코드를 넣으면 잘 동작하기는 하지만 문제는 초기화할 테이블을 직접 작성해줘야 한다. (이상하게 그런 method가 없다)

flyway라는 라이브러리를 추가하면 된다고 하지만 저 작은 기능을 위해 라이브러리를 또 추가하는거 과한거 같아 pass.

근데 아직도 느리다.

결론

가장 큰 문제는 테스트를 통해 서버 API를 document하고 싶었던 욕심이었던거 같다. 테스트는 테스트만!

항상 삽질을 통해 배우는게 많지만... 나중에는 제대로된 테스팅 방법을 공부해야겠다.

0개의 댓글