我们将使用 Spring 的 @WebAppConfiguration 注释来测试 web 控制器。@WebAppConfiguration 是一个类级注释,它档橘侍将加载特定于 web 的 ApplicationContext,即 WebApplicationContext 。
@WebAppConfiguration 所伍唤其中的配置中指定的 web application 的目录的默认路径是 src/main/webapp 。<small>当然,你可以用自己指定的值来覆盖这个默认值。</small>
另外, @WebAppConfiguration 必须与 @ContextConfiguration 结合使用。 <small>@ContextConfiguration 则是用于指定 Spring 配置文件或行吵配置类的。</small>
Spring 3.2 之后出现了 org.springframework.test.web.servlet.MockMvc 类,对 Restful 风格的 Spring MVC 单元测试进行支持。
spring 集成测试中 对mock 的集成实在是太棒了!但是使用请注意一下3个条件。
junit 必须使用4.9以上
同时您的框架必须是用spring mvc
spring 3.2以上旁消明才完美支持
目前使用spring MVC 取代struts2 的很多,spring MVC 的各种灵活让人无比销魂!所以使用spring MVC吧!
以前在对接口(主要是java服务端提供的接口(一般是:webService,restful))进行测试的中 一般用以下俩种方法。测试流程如图:
1 直接使用httpClient
这方法各种运告麻烦
2 使用Spring 提供的RestTemplate
错误不好跟踪,必须开着服务器
使用mockMVC都桥袭不是问题了看使用实例:
使用事例如下:父类
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.web.context.WebApplicationContext
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath:applicationContext.xml",
"classpath:xxxx-servlet.xml" })
public class AbstractContextControllerTests {
@Autowired
protected WebApplicationContext wac
}
子类:
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import com.conlect.oatos.dto.status.RESTurl
import com.qycloud.oatos.server.service.PersonalDiskService
//这个必须使用junit4.9以上才有。
@RunWith(SpringJUnit4ClassRunner.class)
public class PersonalDiskMockTests extends AbstractContextControllerTests {
private static String URI = RESTurl.searchPersonalFile
private MockMvc mockMvc
private String json ="{\"entId\":1234,\"userId\":1235,\"key\":\"new\"}"
@Autowired
private PersonalDiskService personalDiskService
@Before
public void setup() {
//this.mockMvc = webAppContextSetup(this.wac).alwaysExpect(status().isOk()).build()
this.mockMvc = MockMvcBuilders.standaloneSetup(personalDiskService).build()
}
@Test
public void readJson() throws Exception {
this.mockMvc.perform(
post(URI, "json").characterEncoding("UTF-8")
.contentType(MediaType.APPLICATION_JSON)
.content(json.getBytes()))
.andExpect(content().string("Read from JSON: JavaBean {foo=[bar], fruit=[apple]}")
)
}
上面是简单的例子,实际使用起来可以稍做修改。记得导入spring -test jar 包。无需额外配置(是不是很方便!)
当然和junit 的assert 一起用的话效果更好。下面贴点例子。copy就能跑。
Java代码
package com.qycloud.oatos.server.test.mockmvcTest
import static org.junit.Assert.fail
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import java.io.UnsupportedEncodingException
import java.lang.reflect.Field
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import com.conlect.oatos.dto.status.CommConstants
import com.conlect.oatos.dto.status.ErrorType
import com.conlect.oatos.http.PojoMapper
public class MockUtil {
/**
* mock
*
* @param uri
* @param json
* @return
* @throws UnsupportedEncodingException
* @throws Exception
*/
public static String mock(MockMvc mvc, String uri, String json)
throws UnsupportedEncodingException, Exception {
return mvc
.perform(
post(uri, "json").characterEncoding("UTF-8")
.contentType(MediaType.APPLICATION_JSON)
.content(json.getBytes())).andReturn()
.getResponse().getContentAsString()
}
/**
*
* @param re 返回值
* @param object 要转换的对象
* @param testName 当前测试的对象
*/
public static <T>void check(String re, Class<T>object,String testName) {
System.out.println(re)
if (ErrorType.error500.toString().equals(re)) {
System.out.println("-----该接口测试失败:-----"
+ testName)
fail(re)
} else if (CommConstants.OK_MARK.toString().equals(re)) {
System.out.println("-----该接口测试成功:-----"
+ testName)
}else{
System.out.println("-----re----- :"+re)
}
if (object != null) {
if (re.contains(":")) {
try {
T t = PojoMapper.fromJsonAsObject(re, object)
System.out.println("-----该接口测试成功:-----"
+ testName)
} catch (Exception e) {
System.out.println("-----该接口测试失败:-----"
+ testName)
fail(e.getMessage())
}
}
}
}
/**
* 初始化版本信息。每次调用测试用力之前首先更新版本信息
* @param mockMvc
* @param url
* @param fileId
* @param class1
* @return
* @throws UnsupportedEncodingException
* @throws Exception
*/
public static <T>Long updateVersion(MockMvc mockMvc, String url,
Long fileId, Class<T>class1) throws UnsupportedEncodingException, Exception {
String re = mock(mockMvc, url, fileId+"")
T dto = PojoMapper.fromJsonAsObject(re, class1)
Long version = Long.parseLong(dto.getClass().getMethod("getVersion").invoke(dto).toString())
System.out.println("version = "+version)
return version
}
}
使用如下:
Java代码
@RunWith(SpringJUnit4ClassRunner.class)
public class PersonalDiskMockTests extends AbstractContextControllerTests {
private MockMvc mockMvc
private static Long entId = 1234L
private static Long adminId = 1235L
@Autowired
private PersonalDiskService personalDiskService
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(personalDiskService)
.build()
}
/***
* pass
* 全局搜索企业文件
*
* @throws Exception
*/
@Test
public void searchPersonalFile() throws Exception {
SearchFileParamDTO sf = new SearchFileParamDTO()
sf.setEntId(entId)
sf.setKey("li")
sf.setUserId(adminId)
String json = PojoMapper.toJson(sf)
String re = MockUtil.mock(this.mockMvc, RESTurl.searchPersonalFile,
json)
MockUtil.check(re, SearchPersonalFilesDTO.class, "searchPersonalFile")
}
}
当然@setup里面是每个@test执行时都会执行一次的,所以有些需要每次都实例化的参数可以放进来
如下:
Java代码
@Autowired
private ShareDiskService shareDiskService
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(shareDiskService)
.build()
try {
initDatas()
} catch (Exception e) {
e.printStackTrace()
}
}
private void initDatas() throws UnsupportedEncodingException, Exception {
FileIdVersion = MockUtil.updateVersion(mockMvc,RESTurl.getShareFileById,FileId,ShareFileDTO.class)
File2IdVersion = MockUtil.updateVersion(mockMvc,RESTurl.getShareFileById,File2Id,ShareFileDTO.class)
oldPicFolderVersion = MockUtil.updateVersion(mockMvc,RESTurl.getShareFolderById,oldPicFolderId,ShareFolderDTO.class)
}
ok!基本使用大致如此,代码没有些注释,但是很简单,看懂是没问题的。权当抛砖引玉。希望大家加以指正!
SpringMVC单元测试的独立测试;对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,所以为了可以对Controller进行测试,我们引入MockMVC。
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统蚂亩一而且很方便。
★ 服务器端SpringMVC测试的主入口点。
★ 通过MockMVCBuilders建造者的静态方法去建造MockMVCBuilder,MockMvc由MockMVCBuilder构造。
★ 核心方法:perform(RequestBuilder rb),执行一个RequestBuilder请,会自动执行SpringMVC的流程并映射到相应的控制器执行处理,该方法的返回值是一个ResultActions
★ MockMVCBuilder是使用构造者模式来构造MockMvc的构造弯雀器。
★ 主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder。
★ 可以直接使用静态工厂MockMvcBuilders创建即可,不需要直接使用上面两个实现类。
★ 负责创建MockMVCBuilder对象。
两种创建方式
★ 用来构建Request请求的,其主要有两个子类。
★ MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(闷闹森如文件上传使用),即用来Mock客户端请求需要的所有数据。
★ MockMvc.perform后将得到ResultActions
★ andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确。
★ andDo:添加ResultHandler结果处理器,如调试时打印结果到控制台。
★ andReturn:最后返回相应的MvcResult;然后进行自定义验证或下一步的异步处理。
★ MockMvcResultMatchers
用来匹配执行完请求后的**结果验证。
果匹配失败将抛出相应的异常。
包含了很多验证API方法。
★ MockMvcResultHandlers 结果处理器,表示要对结果做处理的需要用到。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)