테스트 환경은 STS에서 spring starter project를 사용했습니다.


@RunWith(SpringRunner.class)

  • junit4 기반으로 테스트 할때 사용합니다.

@ExtendWith(SpringExtension.class)

  • junit5 에서 테스트 할때 사용합니다.

@SpringBootTest/ @AutoConfigureMockMvc

  • 기본적으로 전체 Bean을 스캔하여 등록하기 때문에 사용하기 제일 쉽지만 전체 빈을 스캔하기 때문에 초기화하는데 시간이 오래 걸릴수 있음
  • 실제 서버를 실행하는 것 처럼 테스트 진행 가능
  • SpringBootTest 에 @ExtendWith(SpringExtension.class) 선언이 포함되어 있음

기본 설정

@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
}

테스트 예제

Code: https://github.com/royleej9/spring-sample/blob/master/spring-boot-junit/src/test/java/royleej9/junit/web/user/TestUserController.java

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class TestUserController {

    @Autowired
    private MockMvc mockMvc;

    private static ObjectMapper objectMapper = new ObjectMapper();

    final User user1 = User.builder()
                           .id("id1")
                           .name("test1")
                           .password("pwd123")
                           .createdDate(new Timestamp(System.currentTimeMillis()))
                           .build();

    @Before
    public void setup() throws Exception {
        String param = objectMapper.writeValueAsString(user1);
        this.mockMvc.perform(post("/users")
                    .contentType(MediaType.APPLICATION_JSON).content(param))
                    .andExpect(status().isOk())
                    .andDo(print());
    }

    @Test
    public void testGetUsers() throws Exception {
        // when // then
        this.mockMvc.perform(get("/users").contentType(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$", hasSize(1)))
                    .andDo(print());
    }

    ...
}

문제점(?)

  • @SpringBootTest 사용시 테스트 대상 class를 지정하지 않을 경우 패키지 전체를 스캔하기 때문에 아래와 같은 테스트와 관련이 없는 코드가 자동으로 실행이 됨
  • 테스트를 할때마다 타잔 노래가 출력됨...
package royleej9.junit.web.tarzan;
    ...
@RestController
public class TarzanController {
    public TarzanController() {
        log.info("INIT TarzanController==============================================================");
        final int count = 100000;
        for (int i = 0; i < count; i++) {
            System.out.println("타잔이" + i * 10 + "원 짜리 팬티를 입고" + i * 20 + "원 짜리 칼을 찾고 노래를 한다.");
        }
    }
}

@ContextConfiguration / @ComponentScan

  • @SpringBootTest의 전체 빈을 스캔하지 않고 테스트에 사용하는 패키지만을 스캔하기 위한 설정
  • 테스트 하고자 하는 대상 클래스에서 사용하는 @Component, @Service 등 다른 클래스가 여러 패키지에 속해 있는경우 복잡해지는 문제가 발생
  • 예) 테스트 대상 클래스가 royleej9.junit.web.user 패키지에 속해 있지만 다른 클래스(component, service 등...) royleej9.junit.a, royleej9.junit.c, royleej9.junit.d 와 같이 여러 패키지에 속해 있는 경우

Code: https://github.com/royleej9/spring-sample/blob/master/spring-boot-junit/src/test/java/royleej9/junit/web/user/TestUserControllerContext.java

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = TestUserConfig.class) // config 클래스 추가 
public class TestUserControllerContext {
    @Autowired
    private MockMvc mockMvc;
    ...
    ...
}

Code: https://github.com/royleej9/spring-sample/blob/master/spring-boot-junit/src/test/java/royleej9/junit/web/user/config/TestUserConfig.java

@MapperScan("royleej9.junit.web.user")
@AutoConfigureMybatis
@EnableAutoConfiguration
@ComponentScan(basePackages = "royleej9.junit.web.user")// 스캔 범위를 테스트 대상 패키지로 설정
public class TestUserConfig {
}

@SpringBootTest 어노테이션의 classes 속성 사용하기

@MapperScan("royleej9.junit.web.user") // Mybatis 
@AutoConfigureMybatis                  // Mybatis
@EnableAutoConfiguration
@SpringBootTest(classes= {UserController.class, UserService.class}) // 테스트 대상 클래스 등록 
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class TestUserControllerClasses {
    @Autowired
    private MockMvc mockMvc;
    ...
    ...

@WebMvcTest

Code: https://github.com/royleej9/spring-sample/blob/master/spring-boot-junit/src/test/java/royleej9/junit/web/user/TestUserControllerWebMVC.java

@WebMvcTest(UserController.class) // 테스트 대상 controller 선언 
public class TestUserControllerWebMVC {

    // Usercontroller에서 사용하는 service
    @MockBean
    private UserService userService;

    @Autowired
    private MockMvc mockMvc;

    final User user1 = User.builder()
            .id("id1")
            .name("test1")
            .password("pwd123")
            .createdDate(new Timestamp(System.currentTimeMillis()))
            .build();
    ...

    @Test
    public void testGetUsers() throws Exception {
        // getUsers를 사용할때 리턴되는 값을 선언
        // given
        when(userService.getUsers(null)).thenReturn(Arrays.asList(user1, user2));

        // when // then
        this.mockMvc.perform(get("/users").contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(2)))
                .andDo(print());
    }
    ....
}

참고

'spring' 카테고리의 다른 글

[개발환경] Ubuntu - jdk tar.gz 설치  (0) 2022.09.23
[Springboot-junit] - JPA 테스트/@DataJpaTest  (0) 2022.03.06
[Spring] properties 설정 분리(2)  (0) 2021.02.17
[Spring] properties 설정 분리(1)  (0) 2021.02.17
[spring] json 샘플  (0) 2017.06.27

+ Recent posts