1. 概要

ジャクソンでJSONの逆シリアル化を含むコードを単体テストする場合、 ObjectMapper#readValueメソッドをモックする方が簡単な場合があります。 そうすることで、テストで長いJSON入力を指定する必要がなくなります。

このチュートリアルでは、Mockitoを使用してこれを実現する方法を説明します。

2. Mavenの依存関係

まず、Mavenの依存関係として、mockito-corejackson-databindを使用します。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.3.3</version>
    <scope>test</scope>
 </dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
    <type>bundle</type>
</dependency>

3. ObjectMapperの例

単純なFlowerクラスについて考えてみましょう。

public class Flower {

    private String name;
    private Integer petals;

    public Flower(String name, Integer petals) {
        this.name = name;
        this.petals = petals;
    }

    // default constructor, getters and setters
}

そして、FlowerオブジェクトのJSON文字列表現を検証するためのクラスがあるとします。 コンストラクター引数としてObjectMapperを取ります—これにより、後で簡単にモックすることができます。

public class FlowerJsonStringValidator {
    private ObjectMapper objectMapper;

    public FlowerJsonStringValidator(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public boolean flowerHasPetals(String jsonFlowerAsString) throws JsonProcessingException {
        Flower flower = objectMapper.readValue(jsonFlowerAsString, Flower.class);
        return flower.getPetals() > 0;
    }
}

次に、 Mockito を使用して、バリデーターロジックの単体テストを記述します。

4. Mockitoを使用したユニットテスト

テストクラスを設定することから始めましょう。 ObjectMapper を簡単にモックして、コンストラクター引数としてFlowerStringValidatorクラスに渡すことができます。

@ExtendWith(MockitoExtension.class)
public class FlowerJsonStringValidatorUnitTest {

    @Mock
    private ObjectMapper objectMapper;

    private FlowerJsonStringValidator flowerJsonStringValidator;

    @BeforeEach
    public void setUp() {
        flowerJsonStringValidator = new FlowerJsonStringValidator(objectMapper);
    }
 
    ...
}

テストではJUnit5 を使用しているため、テストクラスに @ExtendWith(MockitoExtension.class)という注釈を付けていることに注意してください。

モックObjectMapperの準備ができたので、簡単なテストを作成しましょう。

@Test
public void whenCallingHasPetalsWithPetals_thenReturnsTrue() throws JsonProcessingException {
    Flower rose = new Flower("testFlower", 100);

    when(objectMapper.readValue(anyString(), eq(Flower.class))).thenReturn(rose);

    assertTrue(flowerJsonStringValidator.flowerHasPetals("this can be a very long json flower"));

    verify(objectMapper, times(1)).readValue(anyString(), eq(Flower.class));
}

ここではObjectMapperをモックしているので、入力を無視して出力に集中し、実際のバリデーターロジックに渡すことができます。 ご覧のとおり、有効なJSON入力を指定する必要はありません。これは、実際のシナリオでは非常に長く困難な場合があります。

5. 結論

この記事では、 ObjectMapper をモックして、その周りに効率的なテストケースを提供する方法を見ました。 最後に、コードはGitHubにあります。