컨텍스트 캐싱 활용하기 및 테스트 중복 코드 제거

홍성민·2023년 8월 13일
0

컨텍스트 캐싱이란 무엇인가

전체 테스트를 돌렸을 때 모든 테스트 메서드마다, 테스트 클래스마다 컨텍스트를 띄우게 된다면 시간이 굉장히 소모된다.

따라서 스프링 부트는 이미 생성된 컨텍스트를 캐싱해서 사용하는 컨텍스트 캐싱을 제공한다.

컨텍스트가 오염되지 않는다면 기존의 캐싱된 컨텍스트를 활용한다.

핵심은 컨텍스트 캐싱을 통해 테스트 성능 최적화를 위해 컨텍스트를 오염시키지 않고 재사용하는 것이다.

컨텍스트 캐싱을 활용할 경우 테스트 격리에 문제가 생기기 때문에 신경을 써야 한다.

컨텍스트를 오염되지 않게 사용하기

레이어별 테스트마다 한번의 컨텍스트를 띄우기 위해 테스트 환경을 구성한다.

인수테스트

인수 테스트의 경우 다음과 같이 구성하여 LineAcceptanceTest extends AcceptanceTest 로 활용했다.

상속을 활용하여 중복코드를 제거할 수 있는 효과 또한 있다.

@Sql({"/scheme.sql", "/data.sql"})
@Sql(value = "/truncate.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AcceptanceTest {

    @Autowired
    protected ObjectMapper objectMapper;

    @LocalServerPort
    private int port;

    @BeforeEach
    public void setUp() {
        RestAssured.port = port;
    }

@DirtiesContext를 활용하면 컨텍스트 캐싱을 활용할 수 없기 때문에 @Sql을 통해 테스트 데이터 격리를 한다.

@Sql을 통해 테스트 격리를 하고자 한다면 spring.sql.init.mode = never 설정을 해주어야 한다.

h2 환경에서 테스트를 진행한다면 다음 sql 구문으로 data.sql의 데이터를 id 변화없이 활용할 수 있다.

TRUNCATE TABLE paths RESTART IDENTITY; //truncate와 함께 auto increment 초기화
TRUNCATE TABLE line RESTART IDENTITY;
TRUNCATE TABLE station RESTART IDENTITY;

WebMvcTest

MockBean을 사용하는 WebMvcTest를 활용한 컨트롤러 단위테스트에선 이런 상속을 활용하는 방법이 유용하다.

매 테스트 클래스마다 MockBean을 새로 등록하게 된다면 컨텍스트를 다시 띄우게 되기 때문이다.

@WebMvcTest({LineController.class, PathController.class, FeeController.class})
public class ControllerTest {

    @Autowired
    protected MockMvc mockMvc;

    @Autowired
    protected ObjectMapper objectMapper;

    @MockBean
    protected LineService lineService;

    @MockBean
    protected PathService pathService;

    @MockBean
    protected FeeService feeService;
}

이와 같이 한 클래스에서 불러올 클래스를 모두 선언하고 필요한 MockBean을 모두 선언하면 한 번의 컨텍스트를 띄우는 것으로 캐싱을 통해 사용할 수 있다.

class FeeControllerTest extends ControllerTest {

    @Test
...

JdbcTest 활용

WebMvcTest에서의 활용과 비슷하다.

@Sql({"/scheme.sql", "/data.sql"})
@Sql(value = "/truncate.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@JdbcTest
public class DaoTest {

    @Autowired
    protected JdbcTemplate jdbcTemplate;

    protected LineDao lineDao;
    protected StationDao stationDao;
    protected PathDao pathDao;
    protected SubwayRepository subwayRepository;

    @BeforeEach
    void setUp() {
        this.lineDao = new LineDao(jdbcTemplate);
        this.stationDao = new StationDao(jdbcTemplate);
        this.pathDao = new PathDao(jdbcTemplate);
        this.subwayRepository = new SubwayRepository(lineDao, stationDao, pathDao);
    }
}

위와 같이 테스트 클래스에서 dao를 활용할 수 있게 protected로 선언해주고 setUp을 통해 모두 생성한다.

profile
안녕하세요

0개의 댓글