Spring 基础 用mock对Controller执行测试(系列号4)

为什么需要用 mock 去测试控制类

因为用 mock 可以模拟 http 请求,这样就不用老是开启服务测试啦...

注意:在此之前需要在pom中添加mvc测试包的依赖。

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>

了解本次学习的文件夹结构:

可以看到,这些都是一些基本的、必要的配置和文件结构。前面用pages文件夹包含对应controller的输出 jsp 页面。

先看看我们定义的控制类:

package com.twm.bookmvc;


import com.twm.bookmvc.dto.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {

    @ResponseBody
    @RequestMapping("/testJson")
    public String testJson(){

        return "book";

    }

    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

    @Autowired
    private Book book;

    @RequestMapping("/book")
    public String getbook(Model model){

        model.addAttribute("firstbook_1",book.getMessage());
        return "book";

    }
}

下面就让我们模拟 http 请求去测试 controller 类的反应。

在test文件夹内最里面的APPTest.java内建立测试

package com.twm.bookmvc;


import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

/**
 * Unit test for simple App.
 */
public class AppTest 
{
    @Test
    public void testBookController(){
        // 创建需要被测试类的实例
        HelloController helloController = new HelloController();
        // 搭建 mvc mock
        MockMvc mockMvc = standaloneSetup(helloController).build();
        try {
            mockMvc.perform(get("/hello")).andExpect(view().name("hello"));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

这里有几点是我们需要注意的:

1. 如果请求名称 /hello 和 jsp 名称相同 比如都是 hello,后台报错:javax.servlet.ServletException: Circular view path [hello]: would dispatch back to the current handler URL [/hello]

因为:

当没有声明ViewResolver时,spring会注册一个默认的ViewResolver,就是JstlView的实例, 该对象继承自InternalResoureView。
JstlView用来封装JSP或者同一Web应用中的其他资源,它将model对象作为request请求的属性值暴露出来, 并将该请求通过javax.servlet.RequestDispatcher转发到指定的URL.
Spring认为, 这个view的URL是可以用来指定同一web应用中特定资源的,是可以被RequestDispatcher转发的。
也就是说,在页面渲染(render)之前,Spring会试图使用RequestDispatcher来继续转发该请求。(由于本项目配置的恰巧也是jsp解析器,所以就造成,请求进入控制器后,又被请求转发,再次进入控制器,无限循环...
解决方案:补全请求转发,让其转入别名视图,跳出循环,或避免请求与页面重名。

2.当涉及到 IOC 或 AOP 时需要开启springmvc才行,无法单独测试。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值