java - 使用 Spring Boot 1.4 MockMVC Controller 方法匹配时,'Cannot subclass final class java.lang.String'

标签 java spring-boot spring-test

我有一个 MockMVC 测试,我正在尝试像这样利用 Controller 方法匹配器:

@Test
public void environmentTopology() throws Exception {
    mockMvc.perform(get("/topology/{environmentId}", "envB"))
            .andExpect(handler().methodCall(on(ManagerController.class)
                 .environmentTopology("envB", true)));
}

这应该允许我验证测试调用了 ManagerController 的 environentTopology 方法。但是,我得到以下异常:

java.lang.IllegalArgumentException: Cannot subclass final class java.lang.String

at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:565)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337)
at org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.initProxy(MvcUriComponentsBuilder.java:611)
at org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.access$000(MvcUriComponentsBuilder.java:89)
at org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder$ControllerMethodInvocationInterceptor.intercept(MvcUriComponentsBuilder.java:725)

最佳答案

解决方案的提示在这里 https://github.com/spring-projects/spring-hateoas/issues/155#issuecomment-36487869

The way the method-to-link functionality works is by creating a proxy for the return type of the method to be able to inspect the previous invocation. As String is a final class it cannot be proxied by definition.

检查方法签名:

@RequestMapping(value = "/topology/{environmentId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String environmentTopology(@PathVariable("environmentId") String environmentId, ...

由于它返回一个字符串,您需要将它包装在一个可代理的类中,例如 ResponseEntity

@RequestMapping(value = "/topology/{environmentId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<String> environmentTopology(@PathVariable("environmentId") String environmentId,

ResponseEntity 包装您的 String 响应,允许测试机制工作。

关于java - 使用 Spring Boot 1.4 MockMVC Controller 方法匹配时,'Cannot subclass final class java.lang.String',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38751956/

相关文章:

java - 使用 stub 的 Spring JUnit 测试究竟如何工作?

java - 无需应用程序测试 Spring/Spring Boot

spring - 测试 Spring Boot Batch 应用程序时如何配置 EntityManagerFactoryBuilder bean?

main 中的 java.lang.ExceptionInInitializerError

java - 使用 AngularJS、Spring 和 Hibernate 保存房间预订

java - 将 bean 传递给 servlet

java - 将 Spring Boot 示例 JNDI 转换为在单独的 Tomcat 实例中工作

java - 如何在 Spring MVC 中更改 BindingResult 中的异常消息

mongodb - Spring Boot MongoDB 连接问题

java - 在失控的 GroovyShell 服务器线程上调用 Thread.stop 是否风险太大?