Spring Boot项目Test启动器进行单元和API测试详解

2019-11-09  本文已影响0人  一块自由的砖

引入test启动器

maven配置

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
</dependency>

依赖关系还引入那些的包

依赖关系图

说明:
spring-boot-test:测试的核心内容。
spring-boot-test-autoconfigure:测试的自动化配置。
Json-path:JSON操作类库。
junit:Java 应用程序单元测试标准类库。
assertj-core:轻量级的断言类库。
mockito-core:Java Mock测试框架。
hamcrest-core:对象匹配器类库。
hamcrest-library:对象匹配器类库。
jsonassert:JSON的断言库。
spring-core:spring集成测试类库。
spring-test:spring集成测试类库。
xmlunit-core:XML单元测试类库。

项目实战

单元测试类的方法

配置JUnitGenerator V2.0(为了偷懒,可以跳过)

通用配置
模板配置

JUnit4.x常用注解说明

@BeforeClass 在所有测试方法前执行一次,一般在方法里面写整体初始化的代码
@AfterClass 在所有测试方法后执行一次,一般方在法里面写销毁和释放资源的代码
@Before 在每个测试方法前执行,一般用来初始化方法
@After 在每个测试方法后执行,在方法执行完成后要做的事情
@Test(timeout = 1000) 测试方法执行超时,超过1000毫秒后算超时,测试将失败
@Test(expected = Exception.class) 测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败
@Ignore(“not ready yet”) 执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类
@Test 编写一般测试用例
@RunWith 在JUnit中有很多个Runner,他们负责调用你的测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。

一个测试类单元测试的执行顺序为:
@BeforeClass –> @Before –> @Test –> @After –> @AfterClass

一个测试方法的调用顺序为:
@Before –> @Test –> @After

断言函数总结
void assertEquals(boolean expected, boolean actual) //检查两个变量或者等式是否平衡
void assertTrue(boolean expected, boolean actual) //检查条件为真
void assertFalse(boolean condition)//检查条件为假
void assertNotNull(Object object)//检查对象不为空
void assertNull(Object object)//检查对象为空
void assertSame(boolean condition)//assertSame() 方法检查两个相关对象是否指向同一个对象
void assertNotSame(boolean condition)//方法检查两个相关对象是否不指向同一个对象
void assertArrayEquals(expectedArray, resultArray)//方法检查两个数组是否相等

实战

在需要编写单元测试的类文件中按快捷键,调用模板的方法(Alt+Insert)默认测试所有所有方法。


通过模板创建测试类

编写单元测试代码,这里是测试github项目用户模块service层的接口实现

package com.springboot.action.saas.modules.user.service.impl;

import com.springboot.action.saas.modules.user.domain.UserMember;
import com.springboot.action.saas.modules.user.dto.UserDto;
import com.springboot.action.saas.modules.user.repository.UserMemberRepository;
import com.springboot.action.saas.modules.user.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/*
 * 业务接口是实现
 * */
@Service
public class MemberServiceImpl implements MemberService {
    @Autowired
    private UserMemberRepository userMemberRepository;
    @Override
    public Long addMember(UserDto member) {
        //检查用户名是否已经存在
        if(null != userMemberRepository.findByName(member.getName())){
            //走存在处理分支
            return -1L;
        }
        UserMember userMember = new UserMember();
        //用户姓名
        userMember.setName(member.getName());
        //加密密码
        BCryptPasswordEncoder encode = new BCryptPasswordEncoder();
        userMember.setPassWord(encode.encode(member.getPassword()));
        //设置创建时间
        userMember.setCreateTime(System.currentTimeMillis());
        //加入到数据库
        userMemberRepository.saveAndFlush(userMember);
        return userMember.getId();
    }

    @Override
    public UserDto findMemberById(Long id) {
        UserDto userDto = new UserDto();
        Optional<UserMember> userMemberOptional = userMemberRepository.findById(id);

        if(!userMemberOptional.isPresent()){
            //用户不存在,走不存在处理
            return null;
        }
        //domain to dto
        UserMember userMember = userMemberOptional.get();
        userDto.setId(userMember.getId());
        userDto.setName(userMember.getName());
        userDto.setPassword(userMember.getPassWord());
        userDto.setEnabled(userMember.getEnabled());
        userDto.setCreateTime(userMember.getCreateTime());
        userDto.setPasswordResetDate(userMember.getPasswordResetDate());

        return userDto;
    }

    @Override
    public UserDto findMemberByName(String name) {
        UserMember userMember = userMemberRepository.findByName(name);
        if (null == userMember) {
            //用户不存在,走不存在处理
            return null;
        }
        //domain to dto
        UserDto userDto = new UserDto();
        userDto.setId(userMember.getId());
        userDto.setName(userMember.getName());
        userDto.setPassword(userMember.getPassWord());
        userDto.setEnabled(userMember.getEnabled());
        userDto.setCreateTime(userMember.getCreateTime());
        userDto.setPasswordResetDate(userMember.getPasswordResetDate());

        return userDto;
    }

    @Override
    public List<UserDto> findAllMember() {
        List<UserMember> userMemberList =  userMemberRepository.findAll();
        List<UserDto> userDtoList = new ArrayList<>();;
        for (int i = 0; i < userMemberList.size(); i++) {
            UserMember userMember = (UserMember) userMemberList.get(i);
            //domain to dto
            UserDto userDto = new UserDto();
            userDto.setId(userMember.getId());
            userDto.setName(userMember.getName());
            userDto.setEnabled(userMember.getEnabled());
            userDto.setCreateTime(userMember.getCreateTime());

            userDtoList.add(userDto);
        }
        return userDtoList;
    }

    @Override
    public void updateMember(UserDto member) {
        UserMember userMember = new UserMember();
        //加密密码
        userMember.setId(member.getId());
        userMember.setName(member.getName());
        userMember.setPassWord(member.getPassword());
        userMember.setEnabled(member.getEnabled());
        userMember.setCreateTime(member.getCreateTime());
        userMemberRepository.saveAndFlush(userMember);
    }
}

测试http请求业务接口

通过使用Spring Test中的MockMvc包的builder类向 DispatcherServlet 发送HTTP请求,并对结果作出断言。本次演示测试github项目用户controller请求接口

package com.springboot.action.saas.modules.user.controller;

import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

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.status;

/**
 * MemberController Tester.
 *
 * @author <Authors name>
 * @version 1.0
 * @since <pre>11/09/2019</pre>
 */
//运行器注解
@RunWith(SpringRunner.class)
//spring boot 测试注解,测试中使用完全运行的web服务器
@SpringBootTest
//由于是Web项目,Junit需要模拟ServletContext,需要给测试类加上@WebAppConfiguration。
@WebAppConfiguration
//注入一个MockMvc实例
@AutoConfigureMockMvc
public class MemberControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Before
    public void before() throws Exception {
        System.out.println("MemberControllerTest before");
    }

    @After
    public void after() throws Exception {
        System.out.println("MemberControllerTest after");
    }

    /**
     * Method: findById(@PathVariable("id") Long id)
     */
    @Test
    public void testFindById() throws Exception {
        //TODO: Test goes here...
        //请求的url,请求的方法是get,添加参数
        RequestBuilder requestBuilder = get("/member/findById")
                .param("id", "1");
        String responseString = mockMvc.perform(requestBuilder)
                .andExpect(status().isOk())
                //返回的状态是200
                .andExpect(MockMvcResultMatchers.jsonPath("$.state").value(1))
                //判断某返回值是否符合预期
                .andDo(print())
                //打印出请求和相应的内容
                .andReturn()
                .getResponse()
                .getContentAsString();
                //将相应的数据转换为字符串
        System.out.println("get方法/member/findById,{}"+responseString);
    }
} 
上一篇下一篇

猜你喜欢

热点阅读