基于Spring MVC(REST API)做单元测试(mockito)
来源:互联网 发布:论文相似性检测软件 编辑:程序博客网 时间:2024/06/06 16:16
来源:http://blog.csdn.net/victor_cindy1/article/details/52126161
最近在公司用的Spring Mvc REST API框架做了一个项目,并且做了基于Spring的单元测试,今天先讲一下基于Spring框架的单元测试,测试使用的是Spring自带的test组件,再结合Mockito一起编写测试案例,以下示例会包括Controller和Service,由于Repository没有自己的逻辑,所以这里就不涉及Repository的单元测试。
首先看一下RestController的代码:
- package com.dhb.springmvc.controller;
-
- import com.dhb.springmvc.entity.User;
- import com.dhb.springmvc.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
-
-
-
-
- @RestController
- @RequestMapping("/springmvc")
- public class UserController {
-
- @Autowired
- private UserService userService;
-
- @RequestMapping(value = "/{name}", method = RequestMethod.GET)
- public String sayHello(@PathVariable String name) {
- return name;
- }
-
-
- @RequestMapping(value = "/api/addUser", method = RequestMethod.POST)
- public int addUserInfo(@RequestBody User user) {
- int result = userService.addUser(user);
- return result;
- }
-
- @RequestMapping(value = "/api/getUser/{id}", method = RequestMethod.GET)
- public User getUserInfo(@PathVariable int id) {
- return userService.findOneUser(id);
- }
-
- @RequestMapping(value = "/api/registerUser", method = RequestMethod.POST)
- public Object registerUser(@RequestBody User user) {
- return userService.register(user);
- }
-
- }
Service的功能代码,代码也比较简单,就是调用Repository做一些增删改查的动作。
- package com.dhb.springmvc.service;
-
- import com.dhb.springmvc.entity.User;
- import com.dhb.springmvc.repository.UserDao;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
-
-
-
- @Service
- public class UserService {
-
- @Autowired
- UserDao userDao;
-
- public int addUser (User user) {
- return userDao.addUser(user);
- }
-
- public User findOneUser(int id) {
- return userDao.findOneUser(id);
- }
-
- public String register(User user) {
- User user2 = userDao.findUserByName(user.getName());
- if(user2 == null) {
- userDao.addUser(user);
- return "成功";
- } else {
- return "失败";
- }
- }
- }
下面是repository代码:
- package com.dhb.springmvc.repository;
-
- import com.dhb.springmvc.entity.User;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.BeanPropertyRowMapper;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.RowMapper;
- import org.springframework.stereotype.Repository;
-
- import javax.sql.DataSource;
-
-
-
-
- @Repository
- public class UserDao {
- private DataSource dataSource;
- private JdbcTemplate jdbcTemplate;
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- this.jdbcTemplate = new JdbcTemplate(dataSource);
- }
-
- public int addUser(User user) {
- String name = user.getName();
- String password = user.getPassword();
- RowMapper<User> mapper = new BeanPropertyRowMapper<>(User.class);
- int result = jdbcTemplate.update("insert into user(name, password) values(?,?)",name, password);
- return result;
- }
-
- public User findOneUser(int id) {
- RowMapper<User> mapper = new BeanPropertyRowMapper<>(User.class);
- User user = jdbcTemplate.queryForObject("select id, name, password from user where id = ?", mapper, id);
- return user;
- }
-
- public User findUserByName(String name) {
- RowMapper<User> mapper = new BeanPropertyRowMapper<>(User.class);
- User user = jdbcTemplate.queryForObject("select id, name, password from user where name = ?", mapper, name);
- return user;
- }
-
- }
entity类:
- package com.dhb.springmvc.entity;
-
-
-
-
-
-
-
- public class User {
- int id;
- String name;
- String password;
-
- public User() {
-
- }
-
- public User(String name, String password) {
- this.name = name;
- this.password = password;
- }
-
- public User(int id, String name, String password) {
- this.id = id;
- this.name = name;
- this.password = password;
- }
-
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
-
- }
增加一个C3P0配置:
- package com.dhb.springmvc.config;
-
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.PropertySource;
-
-
-
-
- @Configuration
-
- public class C3P0DataSourceBuilder {
-
-
-
-
-
- @Bean(name = "dataSource")
- public ComboPooledDataSource getDataSource() {
- try {
-
- ComboPooledDataSource dataSource = new ComboPooledDataSource();
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
- dataSource.setDriverClass("com.mysql.jdbc.Driver");
- dataSource.setUser("root");
- dataSource.setPassword("123456");
- dataSource.setMaxPoolSize(75);
- return dataSource;
- } catch (Exception e) {
- return null;
- }
- }
- }
先看对应的RestController测试:
- package com.dhb.springmvc.controller;
-
- import com.dhb.springmvc.config.DhbWebApplicationInitializer;
- import com.dhb.springmvc.entity.User;
- import com.dhb.springmvc.service.UserService;
- 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 static org.junit.Assert.assertEquals;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
- import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
- import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
- import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-
-
-
- @RunWith(SpringJUnit4ClassRunner.class)
- @WebAppConfiguration
- @ContextConfiguration(classes = {DhbWebApplicationInitializer.class})
- public class UserControllerTest {
- private MockMvc mockMvc;
-
- @Mock
- private UserService userService;
-
- @InjectMocks
- private UserController userController;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
- }
-
-
- @Test
- public void testAdd() {
- int id = 1;
- String name = "邓海波";
- String password = "123456";
-
- User user = new User();
- user.setId(id);
- user.setName(name);
- user.setPassword(password);
- when(userService.addUser(user)).thenReturn(1);
-
- int restUser = userController.addUserInfo(user);
- assertEquals(1, restUser);
-
- verify(userService).addUser(user);
- }
-
- @Test
- public void testGetUserInfo() throws Exception {
- int userId = 1;
- String userName = "邓海波";
- String userPassword = "123456";
-
- User user = new User();
- user.setId(userId);
- user.setName(userName);
- user.setPassword(userPassword);
- when(userService.findOneUser(userId)).thenReturn(user);
-
- mockMvc.perform(get("/springmvc/api/getUser/{id}", userId))
- .andDo(print())
- .andExpect(status().isOk())
- .andExpect(jsonPath("id").value(userId))
- .andExpect(jsonPath("name").value(userName))
- .andExpect(jsonPath("password").value(userPassword));
-
- verify(userService).findOneUser(userId);
- }
-
- }
首先是Spring的几个AnnotateRunWith(SpringJUnit4ClassRunner.class): 表示使用Spring Test组件进行单元测试;WebAppConfiguration: 使用这个Annotate会在跑单元测试的时候真实的启一个web服务,然后开始调用Controller的Rest API,待单元测试跑完之后再将web服务停掉;ContextConfiguration: 指定Bean的配置文件信息,可以有多种方式,这个例子使用的是文件路径形式,如果有多个配置文件,可以将括号中的信息配置为一个字符串数组来表示;然后是Mockito的AnnotateMock: 如果该对象需要mock,则加上此Annotate;InjectMocks: 使mock对象的使用类可以注入mock对象,在上面这个例子中,mock对象是MailService,使用了MailService的是MailController,所以在Controller加上该Annotate;Setup方法MockitoAnnotations.initMocks(this): 将打上Mockito标签的对象起作用,使得Mock的类被Mock,使用了Mock对象的类自动与Mock对象关联。mockMvc: 细心的朋友应该注意到了这个对象,这个对象是Controller单元测试的关键,它的初始化也是在setup方法里面。Test Case首先mock了MailService的send方法,让其返回一个成功的Result对象。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 = /springmvc/api/getUser/1
- Parameters = {}
- Headers = {}
-
- Handler:
- Type = com.dhb.springmvc.controller.UserController
- Method = public com.dhb.springmvc.entity.User com.dhb.springmvc.controller.UserController.getUserInfo(int)
-
- Async:
- Was async started = false
- Async result = null
-
- Resolved Exception:
- Type = null
-
- ModelAndView:
- View name = null
- View = null
- Model = null
-
- FlashMap:
-
- MockHttpServletResponse:
- Status = 200
- Error message = null
- Headers = {Content-Type=[application/json;charset=UTF-8]}
- Content type = application/json;charset=UTF-8
- Body = {"id":1,"name":"邓海波","password":"123456"}
- Forwarded URL = null
- Redirected URL = null
- Cookies = []
再来看一下service对应的测试代码:
- package com.dhb.springmvc.service;
-
- import com.dhb.springmvc.config.DhbWebApplicationInitializer;
- import com.dhb.springmvc.entity.User;
- import com.dhb.springmvc.repository.UserDao;
- 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 static org.hamcrest.Matchers.is;
- import static org.junit.Assert.assertThat;
- import static org.mockito.Matchers.any;
- import static org.mockito.Matchers.anyString;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
-
-
-
-
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(classes = {DhbWebApplicationInitializer.class})
- public class UserServiceTest {
- @Mock
- private UserDao userDao;
-
- @InjectMocks
- private UserService userService;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testRegister() {
- when(userDao.findUserByName(anyString())).thenReturn(null);
- when(userDao.addUser(any(User.class))).thenReturn(0);
-
- assertThat(userService.register(new User("邓海波", "567890")), is("成功"));
-
- verify(userDao).findUserByName(anyString());
- verify(userDao).addUser(any(User.class));
- }
- }
Service的单元测试就比较简单了,大部分内容都在RestController里面讲过,不同的地方就是RestController是使用mockMvc对象来模拟Controler的被测方法,而在Service的单元测试中则是直接调用Service的方法。
这是pom.xml文件
0 0