Mat*_*ano 11 java serialization json mockito jackson
我在使用MockMvc,Mockito和Jackson测试Spring控制器时遇到了这个问题,所以我做了一个简单的类来测试杰克逊的表现.我使用的是jackson-databind:2.3.1和mockito-core:1.9.5.
鉴于此类:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.Serializable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class Person implements Serializable {
private String name;
private int age;
// Public getters and setters...
public static void main(String[] args) {
String name = "Bob";
int age = 21;
ObjectMapper objectMapper = new ObjectMapper();
// attempt serialization with real object
Person person = new Person();
person.setName(name);
person.setAge(age);
try {
System.out.println(objectMapper.writeValueAsString(person));
} catch (JsonProcessingException e) {
e.printStackTrace();
System.err.println("Failed to serialize real object");
}
// attempt serialization with mock object
Person mockPerson = mock(Person.class);
when(mockPerson.getName()).thenReturn(name);
when(mockPerson.getAge()).thenReturn(age);
try {
System.out.println(objectMapper.writeValueAsString(mockPerson));
} catch (JsonProcessingException e) {
e.printStackTrace();
System.err.println("Failed to serialize mock object.");
}
}
Run Code Online (Sandbox Code Playgroud)
Jackson在序列化真实对象方面没有问题,但是当它尝试序列化模拟对象时会抛出JsonMappingException.通过代码调试,它反复调用serializeFields(bean,jgen,provider),卡在内部Mockito属性上.
所以,我的问题是:无论如何迫使杰克逊使用getter方法?我在类上尝试了@JsonIgnoreProperties,在字段上尝试了@JsonIgnore,在方法上尝试了@JsonProperty(在不同的组合中,没有成功).或者,我是否必须编写自己的自定义序列化程序?
谢谢!
这是一个适合您特定情况的解决方案:
首先,您需要创建一个PersonMixin,因为您无法将所需的注释添加到模拟中.
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE)
public interface PersonMixin {
@JsonProperty
String getName();
@JsonProperty
Integer getAge();
}
Run Code Online (Sandbox Code Playgroud)
现在,使用对象映射器,如下面的代码,您将获得与序列化真实对象时相同的结果:
Person mockPerson = mock(Person.class);
when(mockPerson.getName()).thenReturn(name);
when(mockPerson.getAge()).thenReturn(age);
objectMapper.addMixInAnnotations(Person.class, PersonMixin.class);
try {
System.out.println(objectMapper.writeValueAsString(mockPerson));
} catch (JsonProcessingException e) {
e.printStackTrace();
System.err.println("Failed to serialize mock object.");
}
Run Code Online (Sandbox Code Playgroud)
这是我ObjectMapper
在不需要 mixin 的情况下将其整理出来的。
映射器会忽略名称中某处带有“Mockito”的所有成员。
此解决方案避免了每个序列化对象的混合,或注释可能无法访问的代码。
运行以下测试成功并输出{"name":"Jonh"}
。
package test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import org.mockito.Mockito;
public class AppTest extends Mockito {
public void testApp() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return super.hasIgnoreMarker(m) || m.getName().contains("Mockito");
}
});
final String name = "Jonh";
Person mockPerson = mock(Person.class);
when(mockPerson.getName()).thenReturn(name);
System.out.println(mapper.writeValueAsString(mockPerson));
}
public static class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6693 次 |
最近记录: |