spring-test单元测试(三)-spring mvc请求测试

上篇文章中我们介绍了如何在struts环境下,进行模拟action的请求测试,以及我们使用了EasyMock框架,来模拟对象的行为。这篇文章我们会继续介绍spring mvc环境下如何对controller进行单元测试。另外我们带来一种全新的mock框架mockito

 

一、准备工作,引入以下maven坐标

            org.springframework

           spring-test

           3.2.3.RELEASE

           test

       

       

       

            org.mockito

           mockito-core

           2.2.9

           test

       

       

       

            org.glassfish

           javax.el

           3.0.0

           test

                

                            当然别忘记了junit,我们所使用的spring-test框架都是基于junit



    junit
   junit
    4.8.1

 spring-test单元测试(三)-spring mvc请求测试_第1张图片

 

二、整体文件

所有测试文件,均要求放入test目录下(一种规范)

spring-test单元测试(三)-spring mvc请求测试_第2张图片

MyControllerTest.java测试主类


import com.jd.plugin.web.springmvc.service.TestService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.servlet.ModelAndView;

import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import staticorg.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import staticorg.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import staticorg.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * Created by wangxindong on 2016/11/24.
 */
@RunWith(SpringJUnit4ClassRunner.class)
//@WebAppConfiguration
@ContextConfiguration(locations={"classpath*:/spring-config-dispatcher.xml"})
public class MyControllerTest {

    private MockMvc mockMvc;

    @Mock//如果该对象需要mock,则加上此Annotate,在这里我们就是要模拟testService的query()行为
    private TestService testService;

    @InjectMocks//使mock对象的使用类可以注入mock对象,在这里myController使用了testService(mock对象),所以在MyController此加上此Annotate
    MyController myController;


    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(myController).build();//这个对象是Controller单元测试的关键
    }

    @Test
    public voidtestQueryDataFromController() throws Exception{
        //静态引入使得很像人类的语言,当...然后返回...
        when(testService.query("code-1001","name-wangxindong")).thenReturn("成功");//这里模拟行为,返回"成功" 而不是原始的"test-code-name"

        mockMvc.perform(get("/mytest/query/queryData")
                .param("code","code-1001")
                .param("name","name-wangxindong"))
                .andDo(print());
//               .andExpect(status().isOk()).andExpect(content().string(is("{\"status\":\""+ result + "\"}")));

        verify(testService).query("code-1001","name-wangxindong");

    }


}

 

MyController.java 被测试的controller



import com.jd.plugin.web.springmvc.service.TestService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * Created by wangxindong on 2016/11/24.
 */
@RequestMapping("/mytest")
@Controller
public class MyController {

    @Resource
    private TestService testService;

    @RequestMapping(value ="/query/queryData", method = RequestMethod.GET)
    @ResponseBody
    public StringqueryData(@RequestParam(required = true, value = "code", defaultValue= "") String code,
                           @RequestParam(value = "name", defaultValue = "")String name,
                           HttpServletRequest request){

        System.out.println("code:"+code);
        System.out.println("name:"+name);

        String result =testService.query(code,name);

        return "result";
    }
}

 

TestService.java 业务类

/**
 * Created by wangxindong on 2016/11/24.
 */
public interface TestService {


    public String query(Stringcode,String name);
}

 

TestServiceImpl.java业务实现类

import com.jd.plugin.web.springmvc.service.TestService;

/**
 * Created by wangxindong on 2016/11/24.
 */
public class TestServiceImpl implements TestService {

    public String query(String code,String name) {
        System.out.println("TestServiceImplcode:"+code);
        System.out.println("TestServiceImplname:"+name);
        return "test-code-name";
    }
}

 

 

三、文件逐步说明

1、Spring Test 组件使用

@RunWith(SpringJUnit4ClassRunner.class) 表示使用SpringTest组件进行单元测试,这个大家应该都很熟悉了,我们一直是这样使用的
@ContextConfiguration(locations={"classpath*:/spring-config-dispatcher.xml"})指定bean的配置文件,加载上下文环境,我们前面的文章都是这样使用的。其实还有一种文件路径的方式,比如:@ContextConfiguration("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml"),一般个人喜欢第一种方式。

2、mockito使用说明

@Mock

private TestService testService;
如果该对象需要mock,则加上此Annotate,在这里我们就是要模拟testService的query()行为
@InjectMocks
MyController myController;

使mock对象的使用类可以注入mock对象,在这里myController使用了testService(mock对象),所以在MyController此加上此Annotate

 

this.mockMvc = MockMvcBuilders.standaloneSetup(myController).build();//这个对象是Controller单元测试的关键

 

还有几点重要说明:

  • mockMvc.perform: 发起一个http请求。
  • post(url): 表示一个post请求,url对应的是Controller中被测方法的Rest url。
  • param(key, value): 表示一个request parameter,方法参数是key和value。
  • andDo(print()): 表示打印出request和response的详细信息,便于调试。
  • andExpect(status().isOk()): 表示期望返回的Response Status是200。
  • andExpect(content().string(is(expectstring)): 表示期望返回的Response Body内容是期望的字符串。

 

四、运行结果,这些都是print()打印出的内容

MockHttpServletRequest:

         HTTP Method = GET

         Request URI = /mytest/query/queryData

          Parameters = {code=[code-1001],name=[name-wangxindong]}

             Headers = {}

 

             Handler:

                Type =com.jd.plugin.web.springmvc.controller.MyController

              Method = public java.lang.Stringcom.jd.plugin.web.springmvc.controller.MyController.queryData(java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest)

 

  Resolved Exception:

                Type = null

 

        ModelAndView:

           View name = null

                View = null

               Model = null

 

            FlashMap:

 

MockHttpServletResponse:

              Status = 200

       Error message = null

             Headers ={Content-Type=[text/plain;charset=ISO-8859-1], Content-Length=[6]}

        Content type =text/plain;charset=ISO-8859-1

                Body = result

       Forwarded URL = null

      Redirected URL = null

             Cookies= []

 

总结,spring mvc的web请求,我们一样可以通过Spring Test组件来测试。另外mockito这种mock框架来模拟对象行为的时候更加方便,比早先的easymock使用更加简便。

你可能感兴趣的:(SPRING)