测试
软件测试
- 单元测试:对你每个函数单元进行测试,保证每个模块正常工作
- 集成测试:对已经测试过的功能模块进行组装后的测试
- 系统测试:检验软件产品能否与系统的其他部分协调工作
- 验收测试:
测试方法
- 黑盒测试:一直软件功能,根据特定的输入检查是否得到了预期的效果
- 白盒测试:已知软件内部结构细节,可以通过测试证明每种操作是否符合设计要求
单元测试应该具备的特性
- 自动化:调用测试自动化和检查结果自动化
- 彻底性:测试所有可能出现的问题
- 可重复:多次执行的结果一致
- 独立的:单元测试的执行与其它文件无关
- 专业的:单元测试与编码同样重要,在编写单元测试时应遵循Java编码原则。
常见assert断言
- assertArrayEquals(expecteds,actuals)查看两个数组是否相等。
- assertEquals(expecteds,actuals)查看两个对象是否相等,类似于字符串比较使用的equals()方法。(不能比较double类型,double类型比较相等,用减法,然后差值在一个很小的范围内,就可以说这两个相等)
- assertNotEquals(first,second)查看两个对象是否不相等。
- assertNull(object) 查看对象是否为空。
- assertNotNull(object) 查看对象是否不为空。
- assertSame(expected,actual) 查看两个地址一样
- assertNotSame(expected,actual) 查看两个地址不一样
- assertTrue(condition) 查看允许结果是否是true
- assertFalse(condition) 查看允许结果是否是false
- assertThat(actual,matcher) 查看实际结果是否满足指定的条件
- fail() 让测试失败
设置测试前setup(@before)和测试后tearDown(@After)
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
contorller层测试
package com.westos.student.controller;
import com.westos.student.entity.Student;
import com.westos.student.service.StudentServiceInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.ResultSet;
import java.util.List;
@RequestMapping("/api")
@RestController
public class StudentController {
@Autowired
private StudentServiceInterface studentService;
/**
* 前后端分离时一般在api层会给出http状态码
* @param student
* @return
*/
@RequestMapping("/listStudent.do")
public ResponseEntity<List<Student>> listStudent(Student student){
List<Student> result = studentService.listStudent(student);
return new ResponseEntity<List<Student>>(result,HttpStatus.OK);
}
@RequestMapping("/saveStudent.do")
public ResponseEntity<Integer> save(Student student){
Integer result = studentService.save(student);
return new ResponseEntity<Integer>(result,HttpStatus.OK);
}
}
可以选择new 对象进行测试
package com.westos.student.controller;
import com.westos.student.entity.Student;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.util.List;
import static org.junit.Assert.*;
public class StudentControllerTest4 {
private StudentController studentController;
@Before
public void setUp() throws Exception {
//每次测试前new对象
studentController = new StudentController();
}
@Test
public void listStudent() {
//按照学生id查询
Student student = new Student();
student.setId(1);
ResponseEntity<List<Student>> list = studentController.listStudent(student);
//断言状态码为OK
assertEquals(HttpStatus.OK,list.getStatusCode());
//断言查出来1条数据
assertEquals(1,list.getBody().size());
}
@Test
public void save() {
}
}
如果controller中方法参数是HttpServletRequest或者HttpServletResponse的话。
先添加依赖包
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
然后
MockHttpServletRequest request=new MockHttpServletRequest();
request.setParameter("name","zhangsan");
//然后将request传入。相当于模拟给request传参了。
以上的是利用new对象的方式。现在利用spring注入的方式。
spring注入
给测试类前加上注解就可以启动spring了
package com.westos.student.controller;
import com.westos.student.entity.Student;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;
import java.util.List;
import static org.junit.Assert.*;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentControllerTest {
@Autowired
protected WebApplicationContext wac;
@Autowired
private StudentController studentController;
@Before
public void setup(){
assertNotNull(studentController);
}
@Test
public void listStudent() {
ResponseEntity<List<Student>> list = studentController.listStudent(null);
assertEquals(HttpStatus.OK,list.getStatusCode());
assertEquals(2,list.getBody().size());
}
}
测试DAO层
spring.xml中加上提供的jdbc。
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
package com.westos.student.dao;
import com.westos.student.entity.Student;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
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;
import java.util.List;
import static org.junit.Assert.*;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentDAOTest {
@Autowired
protected WebApplicationContext wac;
@Autowired
private StudentDAO dao;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void setup(){
assertNotNull(wac);
assertNotNull(dao);
}
@Test
public void listStudent() {
//执行dao的函数
Student stu=new Student();
stu.setName("Jim");
List<Student> list = dao.listStudent(stu);
assertEquals(2,list.get(0).getId().intValue());
assertEquals("Jim",list.get(0).getName());
}
@Test
public void save(){
//删除库中的多余数据
jdbcTemplate.execute("delete from student where id=3");
Student student=new Student();
student.setId(3);
student.setName("张三");
Integer result=dao.save(student);
assertEquals(1,result.intValue());
//及时删除数据
jdbcTemplate.execute("delete from student where id=3");
}
}
测试service层
方式1,自动装配,使用service中使用dao。
package com.westos.student.service;
import com.westos.student.entity.Student;
import org.junit.Before;
import org.junit.Test;
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;
import java.util.List;
import static org.junit.Assert.*;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentServiceTest {
@Autowired
protected WebApplicationContext wac;
@Autowired
private StudentService studentService;
@Before
public void setup(){
assertNotNull(studentService);
}
@Test
public void listStudent() {
Student student=new Student();
List<Student> list = studentService.listStudent(student);
assertEquals(2,list.size());
}
}
方式2,独立测试,不使用dao,你写完了service层,你的队友dao层还没写完,那你要等他吗?不等,自己测试自己的。
引入包
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>
package com.westos.student.service;
import com.westos.student.dao.StudentDAO;
import com.westos.student.entity.Student;
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.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;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentService2Test {
@Autowired
protected WebApplicationContext wac;
@InjectMocks
private StudentService studentService;
@Mock
private StudentDAO studentDAO;//假的studentDAO
@Before
public void setup(){
//初始化mock
MockitoAnnotations.initMocks(this);
assertNotNull(studentService);
}
@Test
public void listStudent() {
List<Student> result=new ArrayList<Student>();
Student student1=new Student();
student1.setId(1);
student1.setName("John");
result.add(student1);
Student student2=new Student();
student2.setId(2);
student2.setName("Jim");
result.add(student2);
//当调用studentDAO.listStudent(any(Student.class))时,让DAO返回自己设定的值
when(studentDAO.listStudent(any(Student.class))).thenReturn(result);
Student student=new Student();
List<Student> list = studentService.listStudent(student);
assertEquals(2,list.size());
}
@Test
public void save() {
}
}
修改controller层测试,让它可以实现独立测试
package com.westos.student.controller;
import com.westos.student.service.StudentServiceInterface;
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.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 static org.junit.Assert.*;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentController2Test {
@InjectMocks
private StudentController studentController;
@Mock
private StudentServiceInterface studentService;
@Before
public void setup(){
MockitoAnnotations.initMocks(this);
}
@Test
public void listStudent() {
}
@Test
public void save() {
}
}
再次修改controller,模拟HTTP请求(集成测试)
因为以上的测试中,如果代码中有拦截器之类的,是拦截不到的,因为直接调用的controller方法。
package com.westos.student.controller;
import com.alibaba.fastjson.JSON;
import com.westos.student.entity.Student;
import org.junit.Before;
import org.junit.Test;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.context.WebApplicationContext;
import java.util.List;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import static org.junit.Assert.*;
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class StudentController3Test {
private MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Autowired
private StudentController studentController;
@Before
public void setup(){
//构建全部的controller,测试比较全面
// this.mockMvc=webAppContextSetup(this.wac).build();
//构建指定的controller,加载的controller少,速度较快
this.mockMvc=standaloneSetup(studentController).build();
}
@Test
public void listStudent() throws Exception {
String url="/api/listStudent.do";
MvcResult result = this.mockMvc.perform(post(url).param("name", "Jim")).andExpect(status().isOk()).andReturn();
String str = result.getResponse().getContentAsString();
List<Student> list = JSON.parseArray(str, Student.class);
assertEquals(1,list.size());
assertEquals(2,list.get(0).getId().intValue());
assertEquals("Jim",list.get(0).getName());
//gei session添加东西,跳过登陆(登陆信息存在session中)。
result = this.mockMvc.perform(post(url).sessionAttr("LOGINUSERID","admin")).andExpect(status().isOk()).andReturn();
str = result.getResponse().getContentAsString();
list = JSON.parseArray(str, Student.class);
assertEquals(2,list.size());
}
@Test
public void save() {
}
}
谢谢!