春にRestTemplateをモックする

SpringでRestTemplateをモックする

1. 前書き

多くの場合、何らかのWebリクエストを実行するアプリケーションを使用しています。 この動作のテストに関しては、Springアプリでいくつかのoptionsがあります。

In this quick tutorial, we’ll look at just a couple of ways of mocking such calls performed only through a RestTemplate

人気のモックライブラリであるMockitoでテストを開始します。 次に、サーバーの相互作用を定義するための模擬サーバーを作成するメカニズムを提供するSpringTestを使用します。

2. Mockitoの使用

Mockitoを使用して、RestTemplate を完全にモックすることができます。 このアプローチを使用すると、サービスのテストは他のtest involving mockingと同じくらい簡単になります。

単純なEmployeeServiceクラスがあり、HTTPを介して従業員の詳細を取得するとします。

@Service
public class EmployeeService {

    @Autowired
    private RestTemplate restTemplate;

    public Employee getEmployee(String id) {
    ResponseEntity resp =
          restTemplate.getForEntity("http://localhost:8080/employee/" + id, Employee.class);

    return resp.getStatusCode() == HttpStatus.OK ? resp.getBody() : null;
    }
}

前のコードのテストを実装しましょう:__

@RunWith(MockitoJUnitRunner.class)
public class EmployeeServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private EmployeeService empService = new EmployeeService();

    @Test
    public void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
        Employee emp = new Employee(“E001”, "Eric Simmons");
        Mockito
          .when(restTemplate.getForEntity(
            “http://localhost:8080/employee/E001”, Employee.class))
          .thenReturn(new ResponseEntity(emp, HttpStatus.OK));

        Employee employee = empService.getEmployee(id);
        Assert.assertEquals(emp, employee);
    }
}

上記のJUnitテストクラスでは、最初にMockitoに@Mockアノテーションを使用してダミーのRestTemplateインスタンスを作成するように依頼しました。

次に、EmployeeServiceインスタンスに@InjectMocksアノテーションを付けて、ダミーインスタンスを挿入しました。

最後に、テスト方法では、Mockito’s when/then supportを使用してモックの動作を定義しました。

3. Spring Testを使用する

 Spring Testモジュールには、MockRestServiceServer.With this approach, we configure the server to return a particular object when a specific request is dispatched through our RestTemplate instance.という名前のモックサーバーが含まれています。最後に、すべての期待が満たされているかどうかに関係なく、そのサーバーインスタンスでverify()を実行できます。

MockRestServiceServerは、実際にはMockClientHttpRequestFactoryを使用してHTTPAPI呼び出しをインターセプトすることで機能します。 構成に基づいて、予想される要求と対応する応答のリストを作成します。 RestTemplateインスタンスがAPIを呼び出すと、期待値のリストでリクエストを検索し、対応するレスポンスを返します。

したがって、模擬応答を送信するために他のポートでHTTPサーバーを実行する必要がなくなります。

MockRestServiceServerを使用して、同じgetEmployee()の例の簡単なテストを作成しましょう。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpringTestConfig.class)
public class EmployeeServiceMockRestServiceServerUnitTest {

    @Autowired
    private EmployeeService empService;
    @Autowired
    private RestTemplate restTemplate;

    private MockRestServiceServer mockServer;
    private ObjectMapper mapper = new ObjectMapper();

    @Before
    public void init() {
        mockServer = MockRestServiceServer.createServer(restTemplate);
    }

    @Test
    public void givenMockingIsDoneByMockRestServiceServer_whenGetIsCalled_thenReturnsMockedObject()() {
        Employee emp = new Employee("E001", "Eric Simmons");
        mockServer.expect(ExpectedCount.once(),
          requestTo(new URI("http://localhost:8080/employee/E001")))
          .andExpect(method(HttpMethod.GET))
          .andRespond(withStatus(HttpStatus.OK)
          .contentType(MediaType.APPLICATION_JSON)
          .body(mapper.writeValueAsString(emp))
        );

        Employee employee = empService.getEmployee(id);
        mockServer.verify();
        Assert.assertEquals(emp, employee);
    }
}

前のスニペットでは、MockRestRequestMatchersMockRestResponseCreatorsの静的メソッドを使用して、REST呼び出しの期待値と応答を明確で読みやすい方法で定義しました。

import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;

テストクラスのRestTemplateは、EmployeeServiceクラスで使用されるインスタンスと同じである必要があることに注意してください。 これを確実にするために、spring configでRestTemplate Beanを定義し、テストと実装の両方でインスタンスを自動接続しました。

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

MockRestServiceServerを使用すると、統合テストを作成するときに非常に便利で、外部HTTP呼び出しをモックするだけで済みます。

4. 結論

この短い記事では、ユニットテストを作成しながら、HTTP経由で外部のREST API呼び出しをモックするためのいくつかの効果的なオプションについて説明しました。

上記の記事のソースコードはover on GitHubで入手できます。