エキサイト株式会社 メディア事業部エンジニアの中です。
SpringBootでRestTemplateを使った外部APIを実行している実装をテストする方法を記載します。
やり方は単純で、mockitoを使います。
- RestTemplateを使った外部APIを実行している実装をテストする
前提条件
amazonにペットショップの一覧と金額を返すAPIがあると、仮に設定します。
[
{
"id": 1,
"type": "dog",
"price": 249.99
},
{
"id": 2,
"type": "cat",
"price": 124.99
},
{
"id": 3,
"type": "fish",
"price": 0.99
}
]
実装
public interface AmazonStore {
List<PetGoods> getPetGoods();
}
@Component
@RequiredArgsConstructor
public class AmazonStoreImpl implements AmazonStore {
private final RestTemplate restTemplate;
@Value("${spring.amazon.store.pet.url}")
private String url;
@Override
public List<PetGoods> getPetGoods() {
final UriComponents uriComponents = UriComponentsBuilder
.fromUriString(url)
.build();
HttpHeaders headers = new HttpHeaders();
final HttpEntity<String> entity = new HttpEntity<>(headers);
final ResponseEntity<PetGoods[]> exchange = restTemplate
.exchange(uriComponents.toUri(), HttpMethod.GET, entity, PetGoods[].class);
if (exchange.getStatusCode().isError()) {
throw new RuntimeException();
}
return Arrays.asList(exchange.getBody());
}
}
@Data
@Accessors(chain = true)
public class PetGoods {
private long id;
private String type;
private float price;
}
入力例
テストコードです
@ExtendWith(MockitoExtension.class)
class AmazonStoreImplTest {
@Mock
private RestTemplate restTemplate;
@InjectMocks
private AmazonStoreImpl amazonStore;
@Test
@Description("amazon ペットリストの一覧取得")
void getPetGoods() {
final PetGoodsDto dog = new PetGoodsDto()
.setId(1)
.setType("dog")
.setPrice((float) 249.99);
final PetGoodsDto cat = new PetGoodsDto()
.setId(2)
.setType("cat")
.setPrice((float) 124.99);
final PetGoodsDto fish = new PetGoodsDto()
.setId(3)
.setType("fish")
.setPrice((float) 0.99);
final List<PetGoodsDto> result = List.of(dog, cat, fish);
final UriComponents build = UriComponentsBuilder
.fromUriString("http://localhost/petstore/pets")
.build();
HttpHeaders headers = new HttpHeaders();
final HttpEntity<String> entity = new HttpEntity<>(headers);
PetGoodsDto[] returnMock = {
dog, cat, fish
};
final ResponseEntity<PetGoodsDto[]> responseEntity = new ResponseEntity<>(returnMock, HttpStatus.OK);
Mockito.when(restTemplate.exchange(
build.toUri(),
HttpMethod.GET, entity, PetGoodsDto[].class))
.thenReturn(responseEntity);
ReflectionTestUtils.setField(amazonStore, "url", "http://localhost/petstore/pets", String.class);
final List<PetGoodsDto> petGoods = amazonStore.getPetGoods();
Assertions.assertEquals(
result,
petGoods
);
}
}
出力例(テストが成功しているコンソールログです)
BUILD SUCCESSFUL in 2s
ポイント解説
用意するmockを設定します。
@Mock
private RestTemplate restTemplate;
テスト対象をInjectMocksで設定します
@InjectMocks
private AmazonStoreImpl amazonStore;
返却されるResponseEntityを設定します。
final ResponseEntity<PetGoodsDto[]> responseEntity = new ResponseEntity<>(returnMock, HttpStatus.OK);
urlは@ValueでSpringBootのプロパティファイルから設定しているので、以前の記事で設定したReflectionTestUtilsを使って、urlを設定します。
ReflectionTestUtilsで変数に値をセットする - Excite Tech Blog
ReflectionTestUtils.setField(amazonStore, "url", "http://localhost/petstore/pets", String.class);
あとはいつも通りのmockitoを使ってテストをします。
HttpStatus.OK以外を設定すれば、エラーハンドリングのテストもできます。