美文网首页
Spring Restful Api 单元测试

Spring Restful Api 单元测试

作者: 無式 | 来源:发表于2017-07-05 09:04 被阅读0次

    和任何做产品的公司一样,软件公司对其软件产品的质量也是十分看重。
    虽然任何公司都会有测试部门,但软件产品的质量不能完全靠QA同学们的加班来保障。软件质量从程序开发阶段就应该引起重视。
    单元测试便是在开发阶段中保证质量的一种重要方式。

    什么是单元测试

    • 一个单元指的是应用程序中可测试的最小的一组源代码。
    • 源代码中包含明确的输入和输出的每一个方法被认为是一个可测试的单元。
    • 单元测试也就是在完成每个模块后都进行的测试。从确保每个模块没有问题,从而提高整体的程序质量。

    单元测试的目的

    • 是将应用程序的所有源代码,隔离成最小的可测试的单元,保证每个单元的正确性。
    • 理想情况下,如果每个单元都能保证正确,就能保证应用程序整体相当程度的正确性。
    • 单元测试也是一种特殊类型的文档,相对于书面的文档,测试脚本本身往往就是对被测试代码的实际的使用代码,对于帮助开发人员理解被测试单元的使用是相当有帮助的。

    Spring Restful Api 服务单元测试

    就以现在流行的Restful服务来举一个单元测试例子,主要包含ControllerService层。

    测试工具,使用junit+mockito+powermock测试框架

    • 项目新增测试框架的pom依赖:
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.8.4</version>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>1.5.6</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.5.6</version>
        <scope>test</scope>
    </dependency>
    

    创建单元测试基类

    @ContextConfiguration(classes = {WebConfig.class })
    @RunWith(SpringJUnit4ClassRunner.class)  
    public class BaseCtlCfg extends AbstractContextControllerTests  {
    }
    

    Controller层单元测试

    • 测试类继承BaseCtlCfg,加载、初始化Spring相关的配置。
    • @Before中初始化Mock
    • Spring容器中获取Controller实例,通过反射机制用模拟的service类替换原有的service类。
    • 根据测试的Case构建模拟数据。
    • 通过Mockhttp method请求方法调用接口,断言返回的http statusbody是否符合期望。
    public class DraftControllerTest extends BaseCtlCfg{
        @Mock
        private  DraftService draftService;
        @Autowired
        protected WebApplicationContext wac;
        @Before
        public void before(){
            //初始化Mock
            MockitoAnnotations.initMocks(this);
            //获取上下文容器中的controller
            DraftController draftController = (DraftController) wac.getBean("draftController");
            //用mock的Service替换原有的service
            ReflectionTestUtils.setField(draftController, "draftService", draftService);
            }
        @Test
        public void publishTest() throws Exception {
            DraftPublishReq request = new DraftPublishReq();
            request.setPublishMode(1);
            request.setClassIds("495331469627");
            request.setPublishTime(System.currentTimeMillis());
            request.setPublishTime(System.currentTimeMillis() + 2*24*60*60*1000);
    
            String json = JSON.toJSONString(request);
            String uri = "/v0.3/drafts/00691d21-71f4-4115-89d0-a7168c77ef8b/actions/publish";
    
            //构建模拟数据。
            DraftInfo draftInfo = new DraftInfo();
            draftInfo.setIsdel(false);
            //模拟方法调用,当draftId=00691d21-71f4-4115-89d0-a7168c77ef8b时,return draftInfo对象
            when(draftService.get("00691d21-71f4-4115-89d0-a7168c77ef8b")).thenReturn(draftInfo);
    
            String resStr = mockMvc.perform(post(uri, "json")
                    .characterEncoding("UTF-8")
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.valueOf(MockUtil.APPLICATION_JSON))
                    .content(json.getBytes()))
                    .andExpect(status().isOk())
                    .andReturn().getResponse().getContentAsString();
    
            JSONArray jsonArray = JSON.parseArray(resStr);
            Assert.assertEquals(1, jsonArray.size());
        }
    }
    

    Service层测试

    • Mock类的静态方法需要引入注解@RunWith(PowerMockRunner.class)@PrepareForTest(LifecycleServiceV06.class)LifecycleServiceV06.class为Mock的静态方法所在的类)。
    • 通过@Spy注解Mock测试类的真实对象。
    • @Before中初始化Mock,并替换类中要Mock的属性。
    • 构建模拟数据
    • 方法如果有返回值,断言返回值是否符合期望。
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(LifecycleServiceV06.class)
    public class HomeworkBizServiceTest{
    
        @Spy //mock真实对象
        private HomeworkBizService homeworkBizService = new HomeworkBizService();
        @Mock
        private HomeworkExtendRepository homeworkExtendRepository;
    
        @Before
        public void before() {
            //初始化Mock
            MockitoAnnotations.initMocks(this);
            //用mock的repository替换原有的repository
            ReflectionTestUtils.setField(homeworkBizService, "homeworkExtendRepository", homeworkExtendRepository);
        }
    
        @Test
        public void createHomeworkPackage() throws Exception {
            Long userId = 2107222934l;
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(String.valueOf(userId));
            String homeworkId="8b310d5d-ebd2-4798-bff3-2863fe1e1cd7";
            //构建模拟数据
             HomeworkExtend extend = new HomeworkExtend();
            extend.setLcmsHomeworkId(homeworkId);
            LifecycleSession session = new LifecycleSession();
            //mock类静态方法
             PowerMockito.mockStatic(LifecycleServiceV06.class);
            //模拟方法调用返回
             PowerMockito.when(LifecycleServiceV06.uploadHomework(homeworkId, userId)).thenReturn(session);
            //模拟方法调用返回
             when(homeworkExtendRepository.get(homeworkId)).thenReturn(extend);
            //void方法do nothing
            doNothing().when(homeworkBizService).createHomeworkPackage(homeworkId,session);
    
            homeworkBizService.createHomeworkPackage(homeworkId, userInfo);
        }
    }
    

    相关文章

      网友评论

          本文标题:Spring Restful Api 单元测试

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