kok202
스프링 부트의 Mock

2019. 4. 28. 02:21[정리] 기능별 개념 정리/스프링 부트

MOCK 의 사전적 의미 : 모조품

Mocking 과 Spying

테스트할 때 원격 서버의 api 와 통신해봐야 할 수도 있다. 그런데 이렇게 되면 테스트 코드가 원격 서버에 의존적이다. 원격 서버와 통신해야하므로 테스트 코드의 성능도 문제가 된다. 또한 원격 서버가 다운되어 있을 때를 테스트하는 코드가 작성되야 할 수도 있다. 이런 경우 실제로 원격 서버를 다운시킬 수도 없는 노릇이다.이럴 때를 위해서 Spring boot 는 @MockBean과 @SpyBean을 제공한다. + MockRestServiceServer

 

 

 

 

 

@MockBean

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
	@Autowired
	private MyService myService;
    
	@MockBean
	private MyClient myClient;

	@Test
	public void exampleTest() {
		given(myClient.call()).willReturn("hello");
		String result = myService.whatRecieved();
		assertThat(result).isEqualTo("I recieve hello");
	}
}

가정

1. MyClient 는 원격 서버와 통신하는 클라이언트다.

2. MyService 는 MyClient 를 주입받아서 사용한다.

3. MyService 의 whatRecieved() 메소드는 원격 서버에서 받은 값을 "I recieve ~ " 으로 포맷팅해서 return 해준다.

 

@MockBean 의 동작 : MyService 가 MyClient 를 주입받을 때 @MockBean으로 만든 myClient 가 주입된다. 그리고 myClient 의 call() 이라는 메소드는 "hello"을 return 하도록 Mocking 해놨다. MyService 가 whatRecieved 를 호출하면 myClient 의 call 메소드가 연쇄 호출 될 것이고 myClient의 call 메소드가 호출 될 때 실제로 call 메소드를 호출하지 않고 mocking 된 결과 값인 hello 가 return 된다.

 

 

 

 

 

@SpyBean
MockBean 으로 등록된 객체는 빈 객체이기 때문에 만약 MockBean 으로 등록된 객체가 아무것도 mocking 하지 않으면 MockBean 객체의 메소드의 실행은 의미 없는 값을 반환하게 된다. ex) 만약 반환 타입이 String 일 경우 "No content" 가 반환된다.

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
	@Autowired
	private MyService myService;
    
	@MockBean
	private MyClient myClient;

	@Test
	public void exampleTest() {
		String result = myService.whatRecieved();
		assertThat(result).isEqualTo("I recieve hello");
	}
}

위 코드의 myService.whatRecieved(); 결과는 "I recieve No content" 이므로 테스트는 실패한다.

@SpyBean의 동작은 Mocking 하지 않은 메소드에 대해서 기존의 제대로된 메소드를 실행시킨다.

@SpyBean은 기존의 객체에 있는 코드를 그대로 사용하면서 일부만 변경한다. 

 

 

 

 

 

MockRestServiceServer

MockRestServiceServer 를 이용하면 가상의 가짜 서버를 만들고 request에 대한 return 정도를 할 수 있게 만들 수 있다. (호스트가 실제로 뜨는건 아니다. RestTemplate 을 생성할 때 테스트 코드시 이쪽으로 연결되도록 설정하는 것뿐인 듯.) RestTemplate 만 테스트할 수 있는 듯하다.

@RunWith(SpringRunner.class)
@RestClientTest(MyService.class)
public class RestClientTest {
	@Autowired
	private MyService myService;

	@Autowired
	private MockRestServiceServer mockServer;

	@Before
	public void setup(){
		mockServer
			.expect(requestTo("/greet/details"))
			.andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
	}

	@Test
	public void test() throws Exception {
		String greeting = myService.callRestService();
		assertThat(greeting).isEqualTo("hello");
	}
}

 

 

 

 

 

WireMock

WebClient 까지 테스트 가능한 Mock 서버를 만들 수 있다.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
@AutoConfigureWireMock(port = 9999)
public class SymbolizerTemplateTest {
    @Autowired
    private WebClient myWebClient;
    
    // Thread safe
    private static ObjectMapper objectMapper = new ObjectMapper();

    @Before
    public void setUp(){
        createMockServer();
    }

    private void createMockServer(){
        configureFor("localhost",9999);
        stubFor(post(urlPathMatching("/api/user/(.*)"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
                        .withBody(dummyUser())));
    }

    private String dummyUser(){
        User dummyUser = new User("kok202", "Hello world");
        try{ return objectMapper.writeValueAsString(dummyUser);
        }catch (Exception e){ return ""; }
    }
    
    @Test
    public void test() throws Exception{
        ...
    }
}

 

 

 

 

 

아래의 두 포스팅을 재구성하였습니다.

https://kok202.tistory.com/142?category=795332

 

스프링 부트 강의 정리 (19~20 : 테스트, MockBean)

스프링 부트 테스트 spring-boot-starter-test 를 사용하고 이 안에 spring-boot-test, spring-boot-test-autoconfigure 가 있다. JUnit, AssertJ, Harmcrest 라이브러리들을 가져온다. AssertJ : matcher 도 안쓰..

kok202.tistory.com

https://kok202.tistory.com/143?category=795332

 

스프링 부트 강의 정리 (21~22 : 테스트 자동 설정 Annotations)

spring-boot-test-autoconfigure Configuration 을 슬라이싱해서 원하는 설정파일만 불러와서 테스트를 진행할 수 있도록 도와준다. 대부분의 @~Test 은 excludeAutoConfiguration 을 지원하므로 이를 사용하면 된..

kok202.tistory.com

 

 

 

 

 

'[정리] 기능별 개념 정리 > 스프링 부트' 카테고리의 다른 글

스프링 부트 Cache  (0) 2019.05.27
PSA (추상화 계층)  (0) 2019.05.01
스프링 AOP, Transaction  (0) 2019.04.21
Spring boot's NoSQL  (0) 2019.04.21
Spring boot's RestTemplate, WebClient  (0) 2019.04.21