Testing custom JsonDeserializer

蓝咒 提交于 2020-02-06 08:03:05

问题


I am trying to write a unit test to a custom deserializer that is instantiated using a constructor with an @Autowired parameter and my entity marked with @JsonDeserialize.

public class MyDeserializer extends JsonDeserializer<MyEntity> {    
    private final MyBean bean;

    // no default constructor
    @Autowired
    public MyDeserializer(MyBean bean){
        this.bean = bean
    }
    ...
} 

@JsonDeserialize(using = MyDeserializer.class)
public class MyEntity{...}

It works fine in my integration tests where a MockMvc brings up spring serverside.

However with unit tests where I only create ObjectMapper and call mapper.readValue(...), it tries to create a new instance of deserializer using default constructor with no parameters. I tried manually instantiating of a deserializer instance and registering it in ObjectMapper, but it only works if I remove @JsonDeserialize from my entity class (and it breaks my integration tests even if I do the same in my @Configuration class.) - looks related to this: https://github.com/FasterXML/jackson-databind/issues/1300

Test example:

private MyEntity testDeserialize(String jsonFileName){
    MyDeserializer deserializer = new MyDeserializer(mock(MyBean.class));
    SimpleModule module = new SimpleModule();
    module.addDeserializer(MyEntity.class, deserializer);
    ObjectMapper mapper = new ObjectMapper()
        .registerModule(new Jdk8Module())
        .registerModule(module);
    return mapper.readValue(this.getClass().getClassLoader().getResource(jsonFileName), MyEntity.class);
}

I can still test the deserializer behavior calling deserializer.deserialize(...) directly, but this approach doesn't work for me in other unit tests that are not Deserializer's unit tests...

Complete code (tried to use this approach for deserializer):

import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;

public class JacksonInjectExample {
    private static final String JSON = "{\"field1\":\"value1\", \"field2\":123}";

    // HttpResponse in your case
    public static class ExternalObject {
        @Override
        public String toString() {
            return "MyExternalObject";
        }
    }

    @JsonDeserialize(using = MyDeserializer.class)
    public static class MyEntity {
        public String name;
        // make fields public to avoid writing getters in this example
        public String field1;
        public int field2;

        public MyEntity(ExternalObject eo) {
            name = eo.toString();
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static class MyDeserializer extends JsonDeserializer<MyEntity> {

        @Autowired
        private ExternalObject external;

        public MyDeserializer(@JacksonInject final ExternalObject external) {
            this.external = external;
        }

        @Override
        public MyEntity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            return new MyEntity(external);
        }
    }

    @Test
    public void main() throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        final InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue(ExternalObject.class, new ExternalObject());
        mapper.setInjectableValues(injectableValues);

        final MyEntity bean = mapper.readValue(JSON, MyEntity.class);
        System.out.println(bean);
    }
}

来源:https://stackoverflow.com/questions/60061131/testing-custom-jsondeserializer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!