java - Spring Boot JacksonTester 自定义序列化程序未注册

标签 java spring-boot junit jackson

正在尝试通过 Jackson 库运行一些即将到来的工作。我有以下测试模型:

地址.java

package com.example.domain;

import java.time.LocalDate;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class Address {

    private String addressKey;
    private String postalCode;
    private String country;

    @JsonSerialize(using = DateSerializer.class, as = String.class)
    @JsonDeserialize(using = DateDeserializer.class, as = LocalDate.class)
    private LocalDate dateEntered;

    public String getAddressKey() {
        return addressKey;
    }

    public void setAddressKey(String addressKey) {
        this.addressKey = addressKey;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public LocalDate getDateEntered() {
        return dateEntered;
    }

    public void setDateEntered(LocalDate dateEntered) {
        this.dateEntered = dateEntered;
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this, false);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj, false);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE, false);
    }
}

和 dateEntered 字段的自定义序列化器:

DateSerializer.java

package com.example.domain;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import org.springframework.boot.jackson.JsonComponent;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

@JsonComponent
public class DateSerializer extends JsonSerializer<LocalDate> {
    @Override
    public void serialize(LocalDate lc, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        String date = lc.format(DateTimeFormatter.ofPattern("dd MM yyyy"));
        jsonGenerator.writeString(date);
    }
}

我整理了以下测试,利用 @JsonTest 注释来检查序列化程序类是否正在执行我认为应该执行的操作:

地址测试.java

@JsonTest
@RunWith(SpringRunner.class)
public class AddressTest {

@Autowired
private JacksonTester<Address> json;

    @Test
    public void test_Address_serialisation_dateEnteredSerialised() throws Exception {
        final Address address = getTestAddress();

        assertThat(json.write(address))
            .hasJsonPathStringValue("@.dateEntered")
            .extractingJsonPathStringValue("@.dateEntered")
            .isEqualTo("01 05 2018");
    }

    private Address getTestAddress() {
        final Address testAddress = new Address();
        testAddress.setAddressKey("testAddressKey");
        testAddress.setCountry("testCountry");
        testAddress.setPostalCode("testPostalCode");
        testAddress.setDateEntered(LocalDate.of(2018, 5, 1));
        return testAddress;
    }

}

当我运行序列化测试时,我在控制台中得到了这个:

com.fasterxml.jackson.databind.JsonMappingException: Invalid definition for property dateEntered (of type 'Lcom/example/domain/Address;'): Can not refine serialization type [simple type, class java.time.LocalDate] into java.lang.String; types not related

at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:284)
at com.fasterxml.jackson.databind.SerializerProvider.mappingException(SerializerProvider.java:1110)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadPropertyDefinition(SerializerProvider.java:1180)
at com.fasterxml.jackson.databind.ser.PropertyBuilder.buildWriter(PropertyBuilder.java:101)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._constructWriter(BeanSerializerFactory.java:816)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:610)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:399)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:282)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:234)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:168)
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1308)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1279)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:536)
at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:743)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:330)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1427)
at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1158)
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1031)
at org.springframework.boot.test.json.JacksonTester.writeObject(JacksonTester.java:116)
at org.springframework.boot.test.json.AbstractJsonMarshalTester.write(AbstractJsonMarshalTester.java:133)
at com.example.domain.AddressTest.test_Address_serialisation_dateEnteredSerialised(AddressTest.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

据我所知,将 @JsonComponent 添加到类中将允许它在与 @JsonTest 结合使用时被拾取和注册,但基于此,它似乎没有被扫描和添加。我是否遗漏了测试或 src 代码中的一个步骤?值得注意的是,反序列化器的设置方式相同(它以特定格式字符串化日期)并且工作正常。

最佳答案

指定 as = ...@JsonSerialize 内很少需要,特别是当您还指定 using = ... 时.

引自 @JsonSerialize.as 的 javadoc :

...
Note: if using is also used it has precedence (since it directly specifies serializer, whereas this would only be used to locate the serializer) and value of this annotation property is ignored.

在您的情况下:指定 as = String.class似乎是罪魁祸首 未找到的 JSON 序列化程序。

如果您省略它并且在您的 Address 中类就写

@JsonSerialize(using = DateSerializer.class)
@JsonDeserialize(using = DateDeserializer.class)
private LocalDate dateEntered;

然后是 DateSerializer找到并且 AddressTest无一异常(exception)地运行良好。

关于java - Spring Boot JacksonTester 自定义序列化程序未注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51210284/

相关文章:

java - 在程序中的任意点生成 Java 堆栈跟踪

java - Java 中的执行关闭会带来一些麻烦

java - Logback 转换规则参数化

spring-boot - 在 Spring 框架中使用 timeout 属性有什么好处?

java - 如何使用 Junit 和 Spring 手动提交事务

java - Jenkins - 选择测试

java - -t 标志 ("- stalling -"的 SCP 问题)

java - HttpURLConnection 连接重置错误处理

java - 如何在 Spring config.xml 中配置 Cron 时区?

java - 如何使用 JMockit 或其他机制检查方法中局部变量的值