728x90
반응형

📌 Service 레이어 테스트

저번 퍼사드 패턴 적용기 에서
언급했던 테스트에 대해서 써보려고 한다.
바로 정리해보도록 하겠다.
이전의 Mockito 에 대해서 정리한 글이 있다.

📌 테스트 과정

일단 퍼사드 패턴을 적용함으로써
여러개의 서비스를 하나의 퍼사드가 관리해주는 형태로 작성을 했었다.

그러면서 하나의 Service <- 하나의 Repository가 되는 구조를 가지게 되었다.

여기서 @Mock이 등장하게 되었는데,

기존의 @Autowired 방식으로 사용했다면 꿈도 못꾸는 가짜 객체 주입이다.

Service service = new Service(); 해서 @Autowired된 객체를 주입할 수 있을까?

답은 아니라고 생각한다. 의존을 자동으로 주입해주기 때문에 뭘 할당할 수 없는 구조였다.
하지만 생성자 주입을 해준다면??? 얘기는 다르다.

Service service = new Service(repotisory); 가되기 때문에 @Mock으로 가짜 객체를 서비스에

주입해서 POJO 단위 테스트를 진행할 수 있게 된다.

@Service
@Transactional
public class Service {
    private final Repository repository;

    public Service(final Repository repository) {
        this.repository = repository;
    }

    public Foo findByName(final String name) {
        repository.findByName(name).orElseThrow();
    }
}
public interface Repository extends JpaRepository<Foo, Long> {
    Optional<Foo> findByName(final String name);
}
@Getter
public class Foo {
    private String name;
    private int age;

    public Foo (final String name, final int age) {
        this.name = name;
        this.age = age;
    }
}
@ExtendWith(MockitoExtension.class) //Mockito 의존성을 가져온다.
public class ServiceTest {

    @Mock
    private Repository repository;

    @InjectMocks //주입받을 클래스
    private Service service; //(Service service = new Service(repository);) 와 같은구조가 된다.

    @Test
    void test() {
        //given
        Foo foo = new Foo("테스트", 15);

        //when
        // 여기서 mockito로 가짜객체가 어떤 조건을 실행했을 때 어떤 객체를 돌려주게끔 설정해준다.
        BDDMockito.given(repository.findByName(anyString()).willReturn(Optional.ofNullable(foo));

        //then
        Foo foo = service.findByName("테스트");
        verify(service).findByName("테스트"); //service 객체의 findByName메소드에 name값이 '테스트' 인 것을 호출했는지 검증
        Assertions.assertThat(foo.getName()).isEqualTo("테스트");
        Assertions.assertThat(foo.getAge()).isEqualTo(15);
    }
}

이런식으로 POJO 테스트를 진행할 수 있다.
이 구조로 하여금 더더욱 DI가 중요하다는 것을 깨닫고
기초가 중요하다는 것을 다시금 인지하게 되었다.

@Spy, @Mock의 차이

간략하게 한줄로 설명하자면 @Spy는 실제 인스턴스를 사용,

@Mock은 가짜 인스턴스를 사용한다.

그래서 @SpyMockito.when() 이나 BDDMockito.given() 메서드 등으로 메서드의 행위를 지정해 주지 않으면

@Spy 객체를 만들 때 사용한 실제 인스턴스의 메서드를 호출한다.

그래서 @Spy는 실제 인스턴스를 필요로 하기 때문에 인스턴스를 할당 해주어야 사용이 가능하다.

이걸로 미루어 보아 두개를 상황에 따라 적절하게 엮어서 사용해줘야 한다는 것을 느낀다.

물론 적용 해볼 경험이 필요하다!!!!

728x90
반응형

'Spring' 카테고리의 다른 글

Spring Rest Docs 테스트로 문서화를 해보자!  (0) 2022.08.10
Service Layer에 대한 생각  (0) 2022.08.10
Validaion  (0) 2022.08.09
Filter, Interceptor 정리  (0) 2022.08.07

+ Recent posts