1. Обзор
При модульном тестировании кода, включающего десериализацию JSON с помощью Jackson, нам может быть проще имитировать метод ObjectMapper#readValue
. Таким образом, нам не нужно указывать длинные входные данные JSON в наших тестах.
В этом уроке мы увидим, как мы можем добиться этого с помощью Mockito .
2. Зависимости Maven
Прежде всего, в качестве зависимостей Maven мы будем использовать mockito-core
и jackson-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
}
Предположим, у нас есть класс для проверки строкового представления JSON объекта Flower
. Он принимает 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);
}
...
}
Обратите внимание, что мы используем JUnit 5 в наших тестах, поэтому мы аннотировали наш тестовый класс с помощью @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 .