断言错误失败

时间:2018-01-21 09:26:19

标签: java spring mocking

我想测试一个看起来像这样的控制器

@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))

1 个答案:

答案 0 :(得分:2)

你的问题在这里:

String.valueOf(book)

在字符串表示中看起来像这样:

com.valentine.domain.Book@2761156e

这基本上会尝试将您的book转换为它的字符串表示形式,但您没有在toString()类中覆盖Book

无论如何,我建议使用jacksongson之类的内容,然后按以下方式传递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();
}