
问题描述
在使用Mockito创建Mock对象时,尝试使用Jackson ObjectMapper将其序列化为JSON字符串,会导致com.fasterxml.jackson.databind.exc.InvalidDefinitionException异常。例如:
import com.fasterxml.jackson.databind.ObjectMapper;import org.junit.jupiter.api.Test;import org.mockito.Mockito;import static org.mockito.Mockito.mock;public class MockitoObjectMapperTest { @Test public void testSerializeMockObject() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); // 这行代码会抛出 InvalidDefinitionException objectMapper.writeValueAsString(mock(Object.class)); }}
异常信息类似如下:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.mockito.codegen.Object$MockitoMock$nY0RyieU["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["serializationSupport"])
原因分析
Mockito创建的Mock对象是一种特殊的对象,它不是普通的数据结构,而是Mockito框架为了模拟真实对象行为而动态生成的。ObjectMapper在序列化对象时,会递归地遍历对象的成员变量,并尝试将它们序列化为JSON。
在Mock对象中,存在一些Mockito内部使用的成员变量,例如ByteBuddyCrossClassLoaderSerializationSupport。ObjectMapper默认情况下不知道如何序列化这些类型的对象,因此会抛出InvalidDefinitionException异常。
根本原因在于,Mock对象的设计目的不是为了进行序列化,而是为了在单元测试中模拟真实对象的行为。
解决方案
不要尝试直接序列化Mock对象。
Mock对象的主要用途是在单元测试中模拟依赖项的行为,验证代码的逻辑是否正确。如果你需要验证对象的状态,应该验证对象上的方法调用是否产生了预期的结果,而不是直接序列化对象。
如果确实需要将Mock对象的部分状态转换为JSON,可以考虑以下方法:
提取相关数据: 从Mock对象中提取你需要验证的数据,并将这些数据组成一个新的、可序列化的对象。
import com.fasterxml.jackson.databind.ObjectMapper;import org.junit.jupiter.api.Test;import org.mockito.Mockito;import java.util.HashMap;import java.util.Map;import static org.mockito.Mockito.mock;import static org.mockito.Mockito.when;public class MockitoObjectMapperTest { @Test public void testSerializeMockObjectCorrectly() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); // 创建一个 Mock 对象 MyObject mockObject = mock(MyObject.class); when(mockObject.getName()).thenReturn("Test Name"); when(mockObject.getValue()).thenReturn(123); // 提取相关数据到 Map Map data = new HashMap(); data.put("name", mockObject.getName()); data.put("value", mockObject.getValue()); // 序列化 Map 对象 String json = objectMapper.writeValueAsString(data); System.out.println(json); // 输出: {"name":"Test Name","value":123} } // 假设的类 static class MyObject { public String getName() { return null; } public int getValue() { return 0; } }}
自定义序列化器: 如果必须序列化包含Mock对象的复杂结构,可以为Mockito内部使用的类型编写自定义的Jackson序列化器。但是,这通常不是一个好的做法,因为它会将你的代码与Mockito的内部实现细节耦合在一起。
强烈建议避免直接序列化Mock对象,而是专注于验证其行为。
注意事项
在设计单元测试时,应关注验证代码的逻辑和行为,而不是过度关注对象的状态。如果发现需要序列化Mock对象,应该重新审视测试的设计,看看是否有更好的方法来验证代码的正确性。如果确实需要序列化对象,请确保该对象是POJO(Plain Old Java Object),并且ObjectMapper可以正确地处理其所有成员变量。
总结
使用Mockito创建的Mock对象不应该直接使用ObjectMapper进行序列化。这是因为Mock对象不是普通的数据结构,而是Mockito框架为了模拟真实对象行为而动态生成的。如果需要验证对象的状态,应该验证对象上的方法调用是否产生了预期的结果,而不是直接序列化对象。如果必须序列化Mock对象的部分状态,可以考虑提取相关数据并组成一个新的、可序列化的对象。记住,单元测试的核心是验证代码的行为,而不是对象的状态。
以上就是使用Mockito Mock对象时遇到ObjectMapper序列化错误的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/52143.html
微信扫一扫
支付宝扫一扫