Search code examples
javajacksonmockitojackson-databindobjectmapper

Cannot construct instance of X (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value


I'm trying to test a method handleRequest() which is the handler code when an AWS lambda is triggered. The method is as follows:

@Override
public Response handleRequest(Object input, Context context) {
   final Request request =     
      OBJECT_MAPPER.readValue(OBJECT_MAPPER.writeValueAsBytes(input),Request.class);

   // some code that uses request
   .
   .
}

Input to AWS lambda function that is working fine when tested from AWS console -

{"fieldA": "fieldAValue",
"fieldB": "fieldBValue",
"fieldC": "fieldCValue",
"fieldList": [
  {
    "subFieldA": "subFieldAValue",
    "subFieldB": "subFieldBValue",
    "subFieldC": "subFieldCValue",
    "subFieldD": "subFieldDValue",
    "subFieldE": "subFieldEValue"
  }
]
}

My test method -

@Test
public void test_handleRequest() {
   String testInput = 
       "{\"fieldA\":\"fieldAValue\",\"fieldB\":\"fieldBValue\",+    
       "\"fieldC\":\"fieldCValue\"," +
       "\"fieldList\":[" +
       "{\"subFieldA\":\"subFieldAValue\", " +
       "\"subFieldB\":\"subFieldBValue\", " +
       "\"subFieldC\":\"subFieldCValue\", " +
       "\"subFieldD\":\"subFieldDValue\", " +
       "\"subFieldE\":\"subFieldEValue\"}]}";

   handleRequest(testInput, null);

   // code to assert that the actual and expected values are equal.
   .
   .
   .
}

Error when the test method is executed -

Cannot construct instance of 'model.Request' 
(although at least one Creator exists): no String-argument constructor/factory method to 
deserialize from String value ('{"fieldA":"fieldAValue","fieldB":"fieldBValue", 
"fieldC":"fieldCValue","fieldList":[{"subFieldA":"subFieldAValue", 
"subFieldB":"subFieldBValue", "subFieldC":"subFieldCValue", 
"subFieldD":"subFieldDValue", "subFieldE":"subFieldEValue"}]}') at [Source: (byte[])""

The test method is failing with the error that the given input string cannot be mapped to Request class. I got expected result when the AWS lambda is triggered with the same input via AWS console, so I'm pretty sure that the code is perfectly fine.

Is this the right way to build the testInput? Any other alternative way to build testInput so that it can be correctly mapped to Request class when testing?


Solution

  • Converting the json string to Object type using readValue() before passing it to the method under test resolved the error.

    @Test
    public void test_handleRequest() {
       String testInput = 
           "{\"fieldA\":\"fieldAValue\",\"fieldB\":\"fieldBValue\",+    
           "\"fieldC\":\"fieldCValue\"," +
           "\"fieldList\":[" +
           "{\"subFieldA\":\"subFieldAValue\", " +
           "\"subFieldB\":\"subFieldBValue\", " +
           "\"subFieldC\":\"subFieldCValue\", " +
           "\"subFieldD\":\"subFieldDValue\", " +
           "\"subFieldE\":\"subFieldEValue\"}]}";
    
       Object input = new ObjectMapper().readValue(testInput, Object.class);
       handleRequest(input, null);
    
       // code to assert that the actual and expected values are equal.
       .
       .
       .
    }