본문 바로가기
Java

[Java] Mockito 사용법 (2) - 설정, Mock 생성 (@Mock, @Spy, @InjectMocks)

by 노력남자 2022. 9. 6.
반응형

이번 포스팅에선 Mockito 설정하는 방법과 mock 객체 생성관련 어노테이션에 대해 알아보겠습니다.

 

Mockito 설정

 

mockito 최신 버전은 jcenter에 올라와있으니 설정한 후에 의존성을 추가하면 됩니다.

 

repositories { jcenter() }

// maven
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-android</artifactId>
  <version>3.7.7</version>
  <type>pom</type>
</dependency>

// gradle
implementation 'org.mockito:mockito-android:3.7.7'

 

라이브러리 설정 후 Mockito를 사용하려면 테스트 클래스 위에 @ExtendWith(MockitoExtension.class)를 붙혀줘야합니다.

 

@ExtendWith(MockitoExtension.class)
public class mockCreate {
	//...
}

 

Mock 생성

 

mock 생성 관련된 어노테이션은 @Mock, @Spy, @InjectMock 이 있습니다. 하나씩 설명하겠습니다.

 

@Mock

 

@Mock으로 만든 mock 객체는 가짜 객체이며 그 안에 메소드 호출해서 사용하려면 반드시 스터빙(stubbing)을 해야합니다. (스터빙은 아래에서 자세히 다루겠습니다.)

 

만약, 스터빙을 하지 않고 그냥 호출한다면 primitive type은 0, 참조형은 null을 반환합니다.

 

예제

 

테스트를 위해 아래와 같은 UserService를 만들었습니다.

 

public class UserService {

    public User getUser() {
        return new User("effortguy", "1234");
    }

    public int getLoginErrNum() {
        return 1;
    }
}

 

@Mock을 사용하고 스터빙을 하지 않으니 레퍼런스 타입은 null, primitive type은 0을 반환합니다.

 

@ExtendWith(MockitoExtension.class)
public class MockAnnotation {

    @Mock
    UserService userService;

    @Test
    void testReferenceType() {
        assertNull(userService.getUser());
    }

    @Test
    void testPrimitiveType() {
        assertEquals(0, userService.getLoginErrNum());
    }
}

 

 

@Spy

 

@Spy로 만든 mock 객체는 진짜 객체이며 메소드 실행 시 스터빙을 하지 않으면 기존 객체의 로직을 실행한 값을, 스터빙을 한 경우엔 스터빙 값을 리턴합니다.

 

예제

 

테스트를 위해 아래와 같은 ProductService를 만들었습니다.

 

public class ProductService {

    public Product getProduct() {
        return new Product("A001", "monitor");
    }
}

 

스터빙을 안 한 테스트는 기존 객체의 로직을, 스터빙을 한 테스트는 스터빙 값을 리턴하는 것을 볼 수 있습니다.

 

@ExtendWith(MockitoExtension.class)
public class SpyAnnotation {

    @Spy
    ProductService productService;

    @Test
    void testSpy_스터빙X() {
        Product product = productService.getProduct();

        assertEquals("A001", product.getSerial());
    }

    @Test
    void testSpy_스터빙O() {
        Product productDummy = new Product("B001", "keyboard");

        when(productService.getProduct()).thenReturn(productDummy);

        Product product = productService.getProduct();

        assertEquals(productDummy.getSerial(), product.getSerial());
    }
}

 

 

@InjectMock

 

@InjectMock은 DI를 @Mock이나 @Spy로 생성된 mock 객체를 자동으로 주입해주는 어노테이션입니다.

 

예제

 

@Mock, @Spy 예제에서 만들었던 UserService, ProductService를 주입받아 사용하는 OrderService를 만들었습니다.

 

public class OrderService {

    UserService userService;
    ProductService productService;

    OrderService(UserService userService, ProductService productService) {
        this.userService = userService;
        this.productService = productService;
    }

    public User getUser() {
        return userService.getUser();
    }

    public Product getProduct() {
        return productService.getProduct();
    }
}

 

@InjectMocks를 사용하니@Mock, @Spy로 만든 객체들이 자동으로 주입된 것을 볼 수 있습니다.

 

@ExtendWith(MockitoExtension.class)
public class InjectMocksAnnotation {

    @Mock
    UserService userService;

    @Spy
    ProductService productService;

    @InjectMocks
    OrderService orderService;

    @Test
    void testGetUser() {
        assertNull(orderService.getUser());
    }

    @Test
    void testGetProduct() {
        Product product = orderService.getProduct();

        assertEquals("A001", product.getSerial());
    }
}

 

 

@InjectMocks을 쓴 객체의 mock 객체를 주입 받을 수 있는 형태는 Constructor, Property Setter, Field Injection이 있습니다.

 

이전에 DI 관련 정리를 한 것이 있으니 참고하시길 바랍니다.

 

 

[Spring] DI(Dependency Injection)란?

DI(Dependency Injection)란? DI는 디자인 패턴 중 하나이며 객체 간의 의존성을 자신이 아닌 외부에서 받아 느슨한 결합을 하여 유연성, 재사용성, 테스트 용이성을 개선시킨다. DI를 왜 써야하는지 아

effortguy.tistory.com

 

Mockito 공식 홈페이지 @InjecMocks 설명도 있으니 참고하시길 바랍니다.

 

 

InjectMocks - mockito-core 3.7.7 javadoc

Latest version of org.mockito:mockito-core https://javadoc.io/doc/org.mockito/mockito-core Current version 3.7.7 https://javadoc.io/doc/org.mockito/mockito-core/3.7.7 package-list path (used for javadoc generation -link option) https://javadoc.io/doc/org.m

javadoc.io

 

다음 포스팅에선 mock 객체의 스터빙(Stubbing), 검증(Verify)에 대해서 알아보겠습니다.

 

읽어주셔서 감사합니다.

반응형

댓글