我想测试一个看起来像这样的控制器
@PreAuthorize("hasAuthority('USER')")
@RequestMapping("/addItem")
public String addItem(
@ModelAttribute("book") Book book,
@ModelAttribute("qty") String qty,
Model model, Principal principal
) {
User user = userService.findByUsername(principal.getName());
try {
book = bookService.findOne(book.getId());
if (Integer.parseInt(qty) > book.getInStockNumber()) {
model.addAttribute("notEnoughStock", true);
return "forward:/bookDetail?id=" + book.getId();
}
CartItem cartItem = cartItemService.addBookToCartItem(book, user, Integer.parseInt(qty));
model.addAttribute("addBookSuccess", true);
} catch (NullPointerException e) {
}
return "forward:/bookDetail?id=" + book.getId();
}
所以我写了一个接受Text.html的模拟mvc测试 和参数,但似乎我不能将字符串转换回object.And我的测试看起来像这样,我是新手,并试图理解为什么我得到这个错误,如下所示。
@Test
@WithMockUser(username = "V", authorities = {"USER"})
public void addItemToShoppingCart() throws Exception {
CartItem cartItem = new CartItem();
String qty ="2";
Book book = new Book();
book.setActive(true);
User user = new User();
book.setId(1L);
book.getId();
cartItem.setBook(book);
expect(userService.findByUsername("valentine")).andReturn(user);
expect(bookService.findOne(anyLong())).andReturn(book);
expect(cartItemService.addBookToCartItem(book, user, Integer.parseInt(qty))).andReturn(cartItem);
replay();
mockMvc
.perform(get("/shoppingCart/addItem")
.accept(MediaType.TEXT_HTML)
.contentType(MediaType.TEXT_HTML)
.param("book", String.valueOf(book))
.param("qty", qty))
.andExpect(model().attribute("book", book))
.andExpect(model().attribute("qty",qty))
.andExpect(model().attribute("addBookSuccess", true))
.andExpect(view().name("forward:/bookDetail?id=" + cartItem.getId()))
.andReturn();
}
我的堆栈跟踪和错误
12:16:44.682 [main] WARN o.s.w.s.m.s.DefaultHandlerExceptionResolver - Failed to bind request element: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'com.valentine.domain.Book'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'com.valentine.domain.Book@2761156e'; nested exception is java.lang.NumberFormatException: For input string: "com.valentine.domain.Book@2761156e"
MockHttpServletRequest:
HTTP Method = GET
Request URI = /shoppingCart/addItem
Parameters = {book=[com.valentine.domain.Book@2761156e], qty=[2]}
Headers = {Content-Type=[text/html;charset=UTF-8], Accept=[text/html]}
Handler:
Type = com.valentine.bookstore.controller.ShoppingCartController
Method = public java.lang.String com.valentine.bookstore.controller.ShoppingCartController.addItem(com.valentine.domain.Book,java.lang.String,org.springframework.ui.Model,java.security.Principal)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.beans.TypeMismatchException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: No ModelAndView found
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:35)
at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:65)
at org.springframework.test.web.servlet.result.ModelResultMatchers.getModelAndView(ModelResultMatchers.java:272)
at org.springframework.test.web.servlet.result.ModelResultMatchers.access$000(ModelResultMatchers.java:40)
at org.springframework.test.web.servlet.result.ModelResultMatchers$2.match(ModelResultMatchers.java:71)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at com.valentine.bookstore.controller.ShoppingCartControllerTest.addItemToShoppingCart(ShoppingCartControllerTest.java:119)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
有关错误以及如何处理的任何建议?谢谢
现在添加了ObjectMapper后,我将其作为堆栈
ObjectMapper mapper = new ObjectMapper();
String bookstr = mapper.writeValueAsString(book);
mockMvc
.perform(get("/shoppingCart/addItem")
.accept(MediaType.TEXT_HTML)
.contentType(MediaType.TEXT_HTML)
.param("book", bookstr)
.param("qty", qty))
java.lang.AssertionError: No ModelAndView found
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:35)
at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:65)
at org.springframework.test.web.servlet.result.ModelResultMatchers.getModelAndView(ModelResultMatchers.java:272)
at org.springframework.test.web.servlet.result.ModelResultMatchers.access$000(ModelResultMatchers.java:40)
at org.springframework.test.web.servlet.result.ModelResultMatchers$2.match(ModelResultMatchers.java:71)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at com.valentine.bookstore.controller.ShoppingCartControllerTest.addItemToShoppingCart(ShoppingCartControllerTest.java:124)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at
.andExpect(model().attributeExists("book"))
.andExpect(model().attribute("qty",qty))
.andExpect(model().attribute("addBookSuccess", true))
.andExpect(view().name("forward:/bookDetail?id=" + cartItem.getId()))
.andReturn();
说问题来自这里
.andExpect(model().attributeExists("book"))
.andExpect(model().attribute("qty",qty))
.andExpect(model().attribute("addBookSuccess", true))
答案 0 :(得分:2)
你的问题在这里:
String.valueOf(book)
在字符串表示中看起来像这样:
com.valentine.domain.Book@2761156e
这基本上会尝试将您的book
转换为它的字符串表示形式,但您没有在toString()
类中覆盖Book
。
无论如何,我建议使用jackson
或gson
之类的内容,然后按以下方式传递book
:
杰克逊版:
new ObjectMapper().writeValueAsString(book)
gson版本:
new Gson().toJson(book)
使用杰克逊的测试示例:
@Test
@WithMockUser(username = "V", authorities = {"USER"})
public void addItemToShoppingCart() throws Exception {
CartItem cartItem = new CartItem();
String qty = "2";
Book book = new Book();
book.setActive(true);
User user = new User();
book.setId(1L);
book.getId();
cartItem.setBook(book);
expect(userService.findByUsername("valentine")).andReturn(user);
expect(bookService.findOne(anyLong())).andReturn(book);
expect(cartItemService.addBookToCartItem(book, user, Integer.parseInt(qty))).andReturn(cartItem);
replay();
ObjectMapper objectMapper = new ObjectMapper();
mockMvc
.perform(get("/shoppingCart/addItem")
.accept(MediaType.TEXT_HTML)
.contentType(MediaType.TEXT_HTML)
.param("book", objectMapper.writeValueAsString(book))
.param("qty", qty))
.andExpect(model().attribute("book", book))
.andExpect(model().attribute("qty", qty))
.andExpect(model().attribute("addBookSuccess", true))
.andExpect(view().name("forward:/bookDetail?id=" + cartItem.getId()))
.andReturn();
}