DevKim

[Test Code] 단위 테스트 -Service layer & BDDMockito 본문

Spring Boot

[Test Code] 단위 테스트 -Service layer & BDDMockito

on_doing 2021. 7. 20. 19:58
728x90

간단한 게시글 저장의 service layer을 검증해보며 BDDMockito를 사용해보자.


1. 우선 필요한 Mock 객체들을 생성한다.

 

@Mock

- mock 객체를 생성한다

 

@InjectMocks

- @Mock이 붙은 mock객체를 @InjectionMocks이 붙은 객체에 주입시킬 수 있다.

 

실무에서는 @InjectionMocks (Service) @Mock(DAO) 이런식으로 Service 목객체에 DAO 목객체를 주입시켜 사용한다고한다.

@ExtendWith(MockitoExtension.class)
class CommentServiceTest {

    @InjectMocks
    private HoneyService honeyService;

    @Mock
    private HoneyRepository honeyRepository;

 

 

2. DTO를 생성해주고, 임의로 가짜 아이디를 생성해주었다.

테스트를 위하여 ReflectionTestUtils를 이용하여 private 필드값에 직접 id값을 할당해주었다.

@DisplayName("글 생성")
    @Test
    public void test1() throws Exception{
        //given
        HoneyPostApiDto honeyPostApiDto = HoneyPostApiDto.builder()
                .author("author")
                .title("title")
                .author("author")
                .build();
        HoneyPost honeyPost = honeyPostApiDto.toEntity();

        Long fakeId=1L;
        ReflectionTestUtils.setField(honeyPost,"id",fakeId);

 

3. given/willReturn문을 사용하여 어떤 동작을 수행했을 때에 대한 return값을 지정해주고

assertion의 assertThat을 사용하여 검증한다.

//mocking
given(honeyRepository.save(any())).willReturn(honeyPost);
given(honeyRepository.findById(fakeId)).willReturn(Optional.of(honeyPost));

//when
Long postId = honeyService.savePost(honeyPostApiDto);

//then
HoneyPost findPost = honeyRepository.findById(postId).get();

assertThat(honeyPost.getId()).isEqualTo(findPost.getId());
assertThat(honeyPost.getAuthor()).isEqualTo(findPost.getAuthor());
assertThat(honeyPost.getTitle()).isEqualTo(findPost.getTitle());
assertThat(honeyPost.getContent()).isEqualTo(findPost.getContent());

    }

그렇다면 when( ).thenReturn( )이 아닌 given( ).willReturn( )을 사용하는 것에는 어떤 차이점이 있을까?

전자는 Mockito에서. 후자는 BBDMockito에서 제공하는 메소드이다.

 

Mockito란?

Spring은 DI(Dependency Injection)를 지원해주는데, 그 덕분에 개발자는 의존성 주입을 신경 쓰지 않고 객체 간의 의존 관계만 잘 고민해서 객체를 설계하면 된다.

그런데 이런 의존성은 테스트를 하는 시점에서 문제를 발생시킨다. 단위 테스트를 작성할 경우 해당 객체에 대한 기능만을 테스트하고 싶은데 의존성을 가지는 다른 객체에 의해 테스트 결과가 영향을 받을 수 있다는 것이다.

이렇게 의존을 가지는 객체를 우리가 원하는 동작만 하도록 만든 것이 Mock 객체이다.

 

-> when().thenReturn()를 통해 Mock 객체에 원하는 동작을 미리 정하고, 이를 기반으로 테스트를 할 수 있다.

 

BDDMockito란?

BDDMockito의 코드를 살펴보면 Mockito을 상속한 클래스임을 알 수 있다. 

 

BDDMockito BDD를 사용하여 테스트코드를 작성할 때, 시나리오에 맞게 테스트 코드가 읽힐 수 있도록 도와주는 프레임워크이다.

 

실제로 Mockito에서 제공한 기능 그대로 사용할 수 있으면서,

BDD가 추구하는 것처럼 "시나리오에 맞게 테스트 코드가 읽힐 수 있도록" 도와준다.

 

BDD(Behavior-Driven Development)란?

그렇다면 BDDMockito의 BDD가 뭔지 알아보자.

BDD는 Behavior-Driven Development의 약자로 행위 주도 개발을 말한다.

테스트 대상의 상태의 변화를 테스트하는 것이고, 시나리오를 기반으로 테스트하는 패턴을 권장한다.

여기서 권장하는 기본 패턴은 Given, When, Then 구조를 가진다.

 

정리

기존의 Mockito를 사용할 때, given 절에 when이 나오는 등, 가독성을 해치기 때문에

이를 해결하기 위해 기능은 같지만 목적이 다른 BDDMockito 클래스가 등장하였다.

BDDMockito를 사용하여 테스트의 전반적인 가독성을 높일 수 있을 것이라고 예상된다.


+) stub Vs. Mock

- 비슷하지만 다른 말이다.

 

1. stub

: 상태 검증 (state verification)에 사용

stub은 사전에 준비한 가짜 데이터(답) 을 의미한다.

객체가 외부 API에 의존하고 있다고 가정했을 때, API의 응답을 기다릴 수 없으니, 이때 stub을 사용하여 예상되는 결과값을 미리 입력한 뒤 테스트를 진행한다.

-> 행위에 의해 만들어진 상태를 검증

 

2. Mock

: 행위 검증(behavior verification)에 사용

 

->행위 자체를 검증

 

728x90
Comments