14 테스트 대역

개발 99·2025년 4월 30일

테스트 대역 = 가짜 객체나 컴포넌트(실제 객체 대신 역할)

public class UserService{
	
    private final UserRepository userRepository;
    private final VerificationEmailSender verificationEmailSender;
    
    @Transactional
    public User register(UserCreadteDto userCreateDto){
    	User user = User.builder()
        ...
        .build();
        
        user = userRepository.save(user);
        verificationEmailSender.send(user);
        return user;
	}
}

위와 같이 구성할 경우, 테스트를 진행할 때마다 실제 동작을 한다.

메소드를 호출한 결과로 제대로 된 상태 값이 반영됐는지만 확인하면 된다.
(실제 전송은 불필요하다.)

public class DummyVerificationEmailSender implements VerificationEmailSender{
	
    @Overrride
    public void send(User user){
    	// do nothing...
    }
}
public class UserServiceTest{
	
    @Test
    public void ...(){
    	// given UserCreateDto userCreateDto = UserCreateDto.builder()
        ...
        .build();
        
        // when
        UserService userService = UserService.builder()
        ... // <- Mock객체인 new DummyVerificationEmailSender()를 추가한다.
        .build();
        
        // then
        assertThan(user.isPending()).isTrue();
        
    }
}

실제 DB 연결하는 객체 대신에 Mock 객체를 주입해서 단순 테스트만 진행을 한다.
(API 호출 없이 테스트가 가능하다.)

Mock객체의 의의는 해당 메일을 발송하는 부분 외의 나머지가 정상 작동을 하는지 알기 위함이다!

Mock 객체를 이용해서 다양한 시나리오를 연출할 수 있다.

그러나 너무 과도하면, 실제 구현과 거리가 멀어지기 때문에 유의해야 한다.

  • 테스트 대역의 5가지 유형
  1. Dummy
    아무런 동작을 하지 않는다.

  2. Stub
    지정한 값만 반환한다.

  3. Fake
    자체적인 로직이 있다.

  4. Mock
    아무런 동작을 하지 않지만, 어떤 행동이 호출됐는지 기록한다.

  5. Spy
    실제 객체와 똑같이 행동하고, 모든 행동 호출을 기록한다.

14.1 Dummy

아무런 동작도 하지 않는다.
단순히 코드가 정상적으로 돌아가게 하기 위한 역할만 수행하고, 특정 행동이 일어나지 않게 한다.
( Dummy 부분을 제외한 나머지가 정상 작동을 하는기 알기 위해 사용. )

멤버 변수뿐만 아니라 필드 변수 호출로도 가능하다.

public class SomethingFilter extends GenericFilterBean{
	
    @Override
    public void doFilter(
    	...
    ){
    	if(servletRequest.getAttribute("giveMe").equals("text")){
        	servletResponse.setContentType("text/plain");
            
        filterChain.doFilter(...);
        }
    }
}
알고 싶은 것은 giveMe 어트리뷰트가 text일 때 제대로 동작하는지이다.

따라서 ,아래와 같이 수정한다.
```java
public class SomethingFilterTest{
	
    @Test 
    public void ...(){
    	// given
        ServletRequest servletReq = new MockHttpServletRequest();
        servletRequest.setAttribute("giveMe","text");
        ServletResponse servletResponse = new MockHttpServletResponse();
        
        // when
        SomethingFilter somethingFiler = new SomeghingFilter();
        
        somethingFilter.doFilter(...,newFilterChain(){
        	
            @Override
            public void doFilter(...){
            	...// do nothing
                // 이렇게 함으로써, 재귀적으로 빠져 들어가는 것을 방지한다. 오직 1번만 실행
            }
        })
    }
}

14.2 Stub

부본: 원본과 비슷하기 만들어 참고로 보관하는 서류(사본)

실제 객체의 "응답을 최대한 비슷하게" 따라하는 대역.

그래서 Stub은 응답을 원본과 똑같이 반환하는 데만 집중한다.
(원본의 응답을 복제해 똑같은 응답으로 미리 준비하고 이를 바로 반환한다.)

Stub은 미리 준비된 값을 반환하는 대역 객체를 의미한다.
Dummy처럼 실제 구현체의 코드를 실행하지 않는다는 점에서 유사하지만 Dummy보다는 조금 더 발전된 형태이다.
(Dummy는 아무것도 안하지만, Stub은 개발자가 의도한 미리 준비된 값을 반환한다.)

Ex)
실제로 API 호출을 하는 것보다 응답값을 미리 만들어서 반환하는 편이 낫다.

디크스 I/O, 네트워크 호출, JPA도 마찬가지이다.

Stub은 외부 연동을 하는 컴포넌트나 클라이언트를 대체하는 데 자주 사용된다.

profile
구구구구구!

0개의 댓글