您的位置:首页 > 编程语言 > Java开发

Spring Web 单元测试实用HelloWorld(附代码)

2015-11-27 19:45 591 查看

什么是Mokito?它有什么用?

在简单的java 项目中,如果要做单元测试比较方便,利用Junit工具甚至直接写一个main()方法就可以实现。但是到了web项目中,要做单元测试就没那么简单了。笔者往常的开发测试过程往往是这样的,写好一堆的前端后台方法(没有前端,只好自己一起做了),目测过一遍代码逻辑觉得没问题之后就扔到jetty插件中去跑一遍。出现异常后,通过断点调试找到并解决问题,重启一次jetty,重复以上过程。很明显,这样的做法效率是很低的。

最近抽了点时间,学习了一下如果在Java web中进行单元测试。下面首先介绍下如何在项目中简单应用这个技术,随后会尽可能介绍下相关原理。

How?

目标代码展示

项目结构图:



pom.xml

<properties>
<main.basedir>${project.basedir}</main.basedir>
<spring.version>4.2.3.RELEASE</spring.version>
<mybatis.version>3.3.0</mybatis.version>
<mybatis-spring.version>1.2.3</mybatis-spring.version>
<mybatis-generator.version>1.3.2</mybatis-generator.version>
<javax.servlet-api>3.1.0</javax.servlet-api>
<commons-dbcp.version>1.4</commons-dbcp.version>
<mysql-connector-java.version>5.1.35</mysql-connector-java.version>
<jstl.version>1.2</jstl.version>
<jetty.port>8080</jetty.port>
<jackson.codehaus.version>1.9.13</jackson.codehaus.version>
<jackson.fasterxml.version>2.6.3</jackson.fasterxml.version>
<testng.version>6.8.1</testng.version>
<jsonpath.version>0.8.1</jsonpath.version>
<jetty.version>8.1.16.v20140903</jetty.version>
</properties>

<dependencies>

<!-- SPRING -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- SPRING -->

<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- mybatis -->

<!-- mybatis generator -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis-generator.version}</version>
</dependency>
<!-- mybatis generator -->

<!-- javax -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api}</version>
</dependency>
<!-- javax -->

<!-- dbcp database connection pool -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
</dependency>
<!-- dbcp database connection pool -->

<!-- jdbc driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!-- jdbc driver -->

<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- jstl -->

<!-- Jackson -->
<!-- Notice: codehaus is old version of fasterxml -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.codehaus.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.codehaus.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.fasterxml.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.fasterxml.version}</version>
</dependency>
<!-- Jackson -->

<!-- Testing Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>${jsonpath.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Testing Dependencies -->

</dependencies>


MyBatisController.java

/**
* MyBatisController.java
*/
import com.del.entity.Blog;
import com.del.service.MyBatisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("mybatis")
public class MyBatisController {

@Autowired
private MyBatisService myBatisService;

@RequestMapping("getAllBlog")
public ModelAndView getAllBlog(){
ModelAndView modelAndView = new ModelAndView("mybatis");
modelAndView.addObject("result", myBatisService.getBlog(new Blog()));
return modelAndView;
}

@RequestMapping("getBlogById")
public ModelAndView getBlogById(@RequestParam Integer id){
ModelAndView modelAndView = new ModelAndView("mybatis");
Blog blog = new Blog();
blog.setId(id);
modelAndView.addObject("result", myBatisService.getBlog(blog));
return modelAndView;
}

@RequestMapping("getBlogByClass")
public ModelAndView getBlogByClass(@RequestBody Blog blog){
ModelAndView modelAndView = new ModelAndView("mybatis");
modelAndView.addObject("result", myBatisService.getBlog(blog));
return modelAndView;
}

@ResponseBody
@RequestMapping(value = "deleteBlogById", method = RequestMethod.POST)
public Map<String,Object> deleteBlogById(@RequestParam Integer id){
Map<String,Object> resultMap = new HashMap<String, Object>();
boolean isSucceed = myBatisService.delete(id);
if (isSucceed){
resultMap.put("status",Boolean.TRUE);
resultMap.put("message","Success!");
}
else {
resultMap.put("status",Boolean.FALSE);
resultMap.put("message","Error!");
}
return resultMap;
}
}


MyBatisService.java

/**
* MyBatisService.java,提供了对数据库中数据进行增删改的操作。细节不做介绍,有疑问请参照别的资料。
*/

import com.del.dao.IBlogDao;
import com.del.entity.Blog;
import com.del.entity.BlogExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class MyBatisService {

@Autowired
private IBlogDao iBlogDao;

public List<Blog> getBlog(Blog blog){
BlogExample blogExample = new BlogExample();
BlogExample.Criteria criteria = blogExample.createCriteria();
if (blog.getId() != null){
criteria.andIdEqualTo(blog.getId());
}
if (blog.getName() != null){
criteria.andNameEqualTo(blog.getName());
}
if (blog.getSize() != null){
criteria.andSizeEqualTo(blog.getSize());
}
List<Blog> list =  iBlogDao.selectByExample(blogExample);
return list;
}

public boolean insert(Blog blog){
int count = iBlogDao.insert(blog);
return count==1?true:false;
}

public boolean delete(Integer id){
int count = iBlogDao.deleteByPrimaryKey(id);
return count==1?true:false;
}
}


可以看到目标代码很简单,就是监听几个url查找数据库,然后将查询结果通过modal传到jsp,jsp再做相应的展示工作. 大家应该可以很简单看懂.

下面我们就进入正戏,开始做单元测试.

单元测试

UnitTest.java

/**
* UnitTest.java
**/
import com.del.entity.Blog;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
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.context.WebApplicationContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@ContextConfiguration(locations = {"classpath*:platform-services-servlet.xml",
"classpath*:mybatis-context.xml"})
@WebAppConfiguration
public class UnitTest extends AbstractTestNGSpringContextTests {

private MockMvc mockMvc;

@Autowired
private WebApplicationContext webApplicationContext;

@BeforeClass
public void setup(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}

/**
* 简单测试post请求结果
* @throws Exception
*/
@Test(priority = 1)
public void testIndex() throws Exception {
mockMvc.perform(get("/main/index"))
.andExpect(status().isOk())
.andExpect(view().name("main"));
System.out.println("testIndex...");
}

/**
* 测试简单的get请求方法
* @throws Exception
*/
@Test(priority = 2)
public void testSelect() throws Exception {
List<Blog> result = new ArrayList<Blog>();
Blog blog1 = new Blog(1,"first",1);
Blog blog2 = new Blog(2,"second",2);
Blog blog3 = new Blog(3,"three",3);
result.add(blog1);
result.add(blog2);
result.add(blog3);

mockMvc.perform(get("/mybatis/getAllBlog"))
.andExpect(status().isOk())
.andExpect(view().name("mybatis"))
/**
* 这里要注意!!要想用例中可以利用andExpect()方法比较对象,目标类必须有合法的equals()方法!
*/
.andExpect(model().attribute("result",result));
System.out.println("testSelect...");
}

/**
* 测试附带请求参数的post请求方法
* @throws Exception
*/
@Test(priority = 3)
public void testGetBlogById() throws Exception {
Blog blog = new Blog(1,"first",1);
List<Blog> result = new ArrayList<Blog>();
result.add(blog);
mockMvc.perform(post("/mybatis/getBlogById").param("id", "1"))
.andExpect(status().isOk())
.andExpect(model().attribute("result",result));
System.out.println("testGetBlogById...");
}

/**
* 测试附带复杂对象的post请求方法
* @throws Exception
*/
@Test(priority = 4)
public void testGetBlogByClass() throws Exception {
Blog blog = new Blog();
blog.setId(1);

Blog expectBlog = new Blog(1,"first",1);
List<Blog> expectResult = new ArrayList<Blog>();
expectResult.add(expectBlog);
mockMvc.perform(post("/mybatis/getBlogByClass")
.content(asJsonString(blog))
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(model().attribute("result",expectResult));
System.out.println("testGetBlogByClass...");
}

/**
* 测试接收经过jackson转化的json格式返回结果
* @throws Exception
*/
@Test(priority = 5)
public void testDeleteBlogById() throws Exception {
mockMvc.perform(post("/mybatis/deleteBlogById").param("id","3"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.message").value("Success!"));
System.out.println("testDeleteBlogById...");
}

public static String asJsonString(final Object obj) {
try {
final ObjectMapper mapper = new ObjectMapper();
final String jsonContent = mapper.writeValueAsString(obj);
return jsonContent;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

}


Why?

略读测试代码

待完善…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: