본문 바로가기

SW 공부

[Spring] service 테스트 작성 요령

0. 전체 순서

  • 테스트 클래스 만들기 -> 사용할 프로퍼티 만들기 -> 테스트 함수 만들기

1. 테스트 클래스 만들기

  • @RunWith(SpringRunner::class) - JUnit 프레임워크의 테스트 실행 방법을 확장할 때 사용하는 애노테이션이다.
  • @SpringBootTest - 스프링부트 통합테스트 하기 위해서 사용 ( 단위테스트에서는 사용하지 않음)
    • service 테스트에서는 @SpringBootTest 없이 직접 serviceImpl 객체를 만들어서 사용
  • @ActiveProfiles("test") - 특정 profile 선택
    • @Autowired 로 의존성 주입을 받을 때 항상 동일한 빈에서만 받는게 아니고 profile 이라는 네임스페이스로 그룹화가 가능하다. 빈 등록할때 @profiles 라는 어노테이션으로 특정 프로파일에 등록해 놓고 @ActiveProfiles로 특정 profile 의 빈으로 주입 받는다.
  • 특정 Bean 을 사용하기
    • @SpringBootTest(classes = ArticleServiceImpl.class) 또는 
    • @Import(TestConfig.class) 사용한다.

 

2. 사용할 프로퍼티 만들기

  • 단위테스트 프로그램을 작성할 것인데, 따라서 모든 bean 을 사용하지 않음.
  • 테스트의 대상이 되는 클래스의 객체를 생성해야 하는데, 이 객체 생성에 필요한 다른 객체들이 있을 수 있다.
  • @InjectMocks - @Mock이 붙은 목객체를 @InjectMocks이 붙은 객체에 주입시킬 수 있다.
    • 따라서 테스트 대상 객체는 @InjectMocks 으로 만들고 나머지는 @Mock 으로 만들면 자동으로 주입됨
    • @MockBean 은 mock객체를 bean 으로 등록해줌
    • com.nhaarman.mockitokotlin2.mock<T>() 으로 생성해서 사용하는 방법도 있음
    • @Spy는 실제 인스턴스를 사용해서 mocking을 하고, @Mock은 실제 인스턴스 없이 가상의 mock 인스턴스를 직접 만들어 사용
      • @Spy 로 만든 mock 은 초기값(실제 인스턴스)이 항상 필요, 초기값으로 일단 사용하는데
      • mocking 한 메소드는 mocking 한 내용으로 동작한다
// 테스트 대상인 서비스 클래스
@Service
@Transactional(rollbackFor = [Exception::class])
class MyServiceImpl(val otherService: OtherService,
                      val objectMapper: ObjectMapper,
                      val restTemplate: RestTemplate) {
                  ...
                  ...
}

// 테스트 클래스
@RunWith(SpringRunner::class)
@ActiveProfiles("test")
class MyServiceTest {
    // 테스트 대상 클래스만 bean 으로 가져오고 나머지는 mock 으로 만듬
    @InjectMocks
    lateinit var myServiceImpl: MyServiceImpl
    
    // Mock 객체 만들기
    var otherService = mock<OtherService> {}
    
    
}