1. Overview
1.概述
When unit testing code that involves deserializing JSON with Jackson, we might find it easier to mock the ObjectMapper#readValue method. By doing so, we don’t need to specify long JSON inputs in our tests.
当单元测试涉及用Jackson反序列化JSON的代码时,我们可能会发现模拟ObjectMapper#readValue方法会更容易。通过这样做,我们不需要在测试中指定长的JSON输入。
In this tutorial, we’re going to see how we can achieve this using Mockito.
在本教程中,我们将看到如何使用Mockito实现这一目标。
2. Maven Dependencies
2.Maven的依赖性
First of all, as Maven dependencies, we’re going to use mockito-core and jackson-databind:
首先,作为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. An ObjectMapper Example
3.一个ObjectMapper例子
Let’s consider a simple Flower class:
让我们考虑一个简单的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
}
And suppose we have a class for validating a JSON string representation of a Flower object. It takes ObjectMapper as a constructor argument — this makes it easy for us to mock it later:
假设我们有一个用于验证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;
}
}
Next, we’ll use Mockito to write unit tests for the validator logic.
接下来,我们将使用Mockito 来为验证器逻辑编写单元测试。
4. Unit Testing With Mockito
4.用Mockito进行单元测试
Let’s start by setting up our test class. We can easily mock an ObjectMapper and pass it as a constructor argument to our FlowerStringValidator class:
让我们从设置我们的测试类开始。我们可以轻松地模拟一个ObjectMapper,并将其作为构造参数传递给我们的FlowerStringValidator类。
@ExtendWith(MockitoExtension.class)
public class FlowerJsonStringValidatorUnitTest {
@Mock
private ObjectMapper objectMapper;
private FlowerJsonStringValidator flowerJsonStringValidator;
@BeforeEach
public void setUp() {
flowerJsonStringValidator = new FlowerJsonStringValidator(objectMapper);
}
...
}
Note that we’re using JUnit 5 in our tests, so we’ve annotated our test class with @ExtendWith(MockitoExtension.class).
请注意,我们在测试中使用JUnit 5,所以我们用@ExtendWith(MockitoExtension.class)注释了我们的测试类。
Now that we have our mock ObjectMapper ready to go, let’s write a simple test:
现在我们的模拟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));
}
Since we’re mocking ObjectMapper here, we can ignore its input and focus on its output, which is then passed to the actual validator logic. As we can see, we don’t need to specify valid JSON input, which can be very long and difficult in a real-world scenario.
由于我们在此模拟ObjectMapper,我们可以忽略它的输入,而关注它的输出,然后将其传递给实际的验证器逻辑。正如我们所看到的,我们不需要指定有效的JSON输入,在真实世界的场景中,JSON输入可能非常长,而且很困难。
5. Conclusion
5.总结
In this article, we saw how to mock ObjectMapper to provide efficient test cases around it. Finally, the code can be found over on GitHub.
在这篇文章中,我们看到了如何模拟ObjectMapper 以提供围绕它的高效测试案例。最后,代码可以在GitHub上找到over。