美文网首页
Spring Boot项目Test启动器进行单元和API测试详解

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

作者: 一块自由的砖 | 来源:发表于2019-11-09 18:23 被阅读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);
        }
    } 
    

    相关文章

      网友评论

          本文标题:Spring Boot项目Test启动器进行单元和API测试详解

          本文链接:https://www.haomeiwen.com/subject/ohrgbctx.html