java - Spring MockMvc UnsupportedOperationException after upgrading to new spring version -
i'm working on migration spring 3.2.3.release spring 4.2.0.release. got stuck because existing tests start failing. code looks (simplified):
@webappconfiguration @contextconfiguration(classes = [testconfig.class]) class mvctest extends specification { @autowired webapplicationcontext context mockmvc mockmvc @subject mycontroller controller def setup() { controller = new mycontroller() mockmvc = mockmvcbuilders.standalonesetup(controller).build() } def "should not allow save invalid entity"() { when: def result = mockmvc.perform(post("/people") .content('''{ "name": "", "age": 21, "sex": 1 }''') .contenttype(mediatype.application_json) .accept(mediatype.application_json)) then: result.anddo(print()) .andexpect(status().isbadrequest()) .andexpect(jsonpath('$.message').value("name cannot empty.")) } }
mycontroller.java
@controller public class mycontroller { @requestmapping(method = requestmethod.post, value = "/people", produces = "application/json", consumes = "application/json") @responsebody public response create(@requestbody @valid person person) { //save person repository. debugger not entering line... } }
person.java:
public class person { private int age; @notempty(message = "name cannot empty.") private string name; @notnull @jsonserialize(using = sextypeserializer.class) @jsondeserialize(using = sextypedeserializer.class) private sex sex; //getters, setters, other methods }
testconfig.groovy
@enablewebmvc @configuration class testconfig { @bean @primary public objectmapper objectmapper() { def objectmapper = new objectmapper() def jacksonmodule = new simplemodule() jacksonmodule.adddeserializer(sex.class, new sextypedeserializer()) jacksonmodule.addserializer(sex.class, new sextypeserializer()) objectmapper.registermodule(jacksonmodule) objectmapper } }
stacktrace:
java.lang.unsupportedoperationexception @ org.springframework.test.web.servlet.setup.stubwebapplicationcontext$stubbeanfactory.createbean(stubwebapplicationcontext.java:369) @ org.springframework.http.converter.json.springhandlerinstantiator.deserializerinstance(springhandlerinstantiator.java:68) @ com.fasterxml.jackson.databind.deser.defaultdeserializationcontext.deserializerinstance(defaultdeserializationcontext.java:111) @ com.fasterxml.jackson.databind.deser.basicdeserializerfactory.finddeserializerfromannotation(basicdeserializerfactory.java:1436) @ com.fasterxml.jackson.databind.deser.beandeserializerfactory.constructsettableproperty(beandeserializerfactory.java:765) @ com.fasterxml.jackson.databind.deser.beandeserializerfactory.addbeanprops(beandeserializerfactory.java:544) @ com.fasterxml.jackson.databind.deser.beandeserializerfactory.buildbeandeserializer(beandeserializerfactory.java:270) @ com.fasterxml.jackson.databind.deser.beandeserializerfactory.createbeandeserializer(beandeserializerfactory.java:168) @ com.fasterxml.jackson.databind.deser.deserializercache._createdeserializer2(deserializercache.java:401) @ com.fasterxml.jackson.databind.deser.deserializercache._createdeserializer(deserializercache.java:350) @ com.fasterxml.jackson.databind.deser.deserializercache._createandcache2(deserializercache.java:263) @ com.fasterxml.jackson.databind.deser.deserializercache._createandcachevaluedeserializer(deserializercache.java:243) @ com.fasterxml.jackson.databind.deser.deserializercache.hasvaluedeserializerfor(deserializercache.java:193) @ com.fasterxml.jackson.databind.deserializationcontext.hasvaluedeserializerfor(deserializationcontext.java:344) @ com.fasterxml.jackson.databind.objectmapper.candeserialize(objectmapper.java:2035) @ org.springframework.http.converter.json.abstractjackson2httpmessageconverter.canread(abstractjackson2httpmessageconverter.java:151) @ org.springframework.web.servlet.mvc.method.annotation.abstractmessageconvertermethodargumentresolver.readwithmessageconverters(abstractmessageconvertermethodargumentresolver.java:187) @ org.springframework.web.servlet.mvc.method.annotation.requestresponsebodymethodprocessor.readwithmessageconverters(requestresponsebodymethodprocessor.java:148) @ org.springframework.web.servlet.mvc.method.annotation.requestresponsebodymethodprocessor.resolveargument(requestresponsebodymethodprocessor.java:125) @ org.springframework.web.method.support.handlermethodargumentresolvercomposite.resolveargument(handlermethodargumentresolvercomposite.java:78) @ org.springframework.web.method.support.invocablehandlermethod.getmethodargumentvalues(invocablehandlermethod.java:162) @ org.springframework.web.method.support.invocablehandlermethod.invokeforrequest(invocablehandlermethod.java:129) @ org.springframework.web.servlet.mvc.method.annotation.servletinvocablehandlermethod.invokeandhandle(servletinvocablehandlermethod.java:111) @ org.springframework.web.servlet.mvc.method.annotation.requestmappinghandleradapter.invokehandlermethod(requestmappinghandleradapter.java:806) @ org.springframework.web.servlet.mvc.method.annotation.requestmappinghandleradapter.handleinternal(requestmappinghandleradapter.java:729) @ org.springframework.web.servlet.mvc.method.abstracthandlermethodadapter.handle(abstracthandlermethodadapter.java:85) @ org.springframework.web.servlet.dispatcherservlet.dodispatch(dispatcherservlet.java:959) @ org.springframework.web.servlet.dispatcherservlet.doservice(dispatcherservlet.java:893) @ org.springframework.web.servlet.frameworkservlet.processrequest(frameworkservlet.java:970) @ org.springframework.web.servlet.frameworkservlet.dopost(frameworkservlet.java:872) @ javax.servlet.http.httpservlet.service(httpservlet.java:688)
custom serializers provided , working correctly previous version of spring. think there wrong configuration, because of fact such method being called:
stubwebapplicationcontext.java
@override public <t> t createbean(class<t> beanclass) { throw new unsupportedoperationexception(); }
looks other implementation of createbean should used. ideas problem?
this breaking change introduced in spring framework 4.1.3.
i have created bug report make sure gets resolved:
https://jira.spring.io/browse/spr-13375
thanks bringing our attention!
by way, when use mockmvcbuilders.standalonesetup()
, there no need load applicationcontext
via @contextconfiguration
, @webappconfiguration
. if analyze test class, see in fact not using webapplicationcontext
have @autowired
test. can safely remove of configuration.
note testconfig
not used in mockmvc
since using mockmvcbuilders.standalonesetup()
test instance of controller directly. in other words, custom sextypedeserializer
not used in test configured this. if want continue use stand-alone setup, can configure mappingjackson2httpmessageconverter
custom configured objectmapper
(along custom serializer, etc.) , pass standalonemockmvcbuilder
via setmessageconverters(...)
method.
as alternative, consider using mockmvcbuilders.webappcontextsetup(context)
in order use sextypedeserializer
in tests along rest of production spring mvc configuration.
Comments
Post a Comment