Unit Test(UT)单元测试

我们项目一般都是 MVC 分层的,而单元测试主要是在 Dao 层和 Service 层上进行编写。从项目结构上来说,Service 层是依赖 Dao 层的,但是从单元测试角度,对某个 Service 进行单元的时候,他所有依赖的类都应该进行Mock。而 Dao 层单元测试就比较简单了,只依赖数据库中的数据。

一 、Mockito

Mockito是mocking框架,它让你用简洁的API做测试,是为了简化单元测试过程中测试上下文 ( 或者称之为测试驱动函数以及桩函数 ) 的搭建而开发的工具
入坑Mockito吧,骚年!
Unit Test(UT)单元测试_第1张图片
不说废话,看如何使用就好!

1 pom导入依赖

SpringBoot 中的 pom.xml 文件需要添加的依赖:

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>

该依赖中已经有单元测试所需的大部分依赖,如:junit、mockito、hamcrest。若为其他 spring 项目,需要自己添加 Junit 和 mockito 项目。

2 mockito使用

常用方法汇总:(温馨提示,Ctrl+F示例名在代码中找示例 ^ _ ^

方法名 描述 示例
Mockito.mock(classToMock) 模拟对象 test_mock_class()
Mockito.verify(mock) 验证行为是否发生
Mockito.when(methodCall).thenReturn(value1).thenReturn(value2) 触发时第一次返回value1,第n次都返回value2
Mockito.doThrow(toBeThrown).when(mock).[method] 模拟抛出异常
Mockito.mock(classToMock,defaultAnswer) 使用默认Answer模拟对象
Mockito.when(methodCall).thenReturn(value) 参数匹配
Mockito.doReturn(toBeReturned).when(mock).[method] 参数匹配(直接执行不判断)
Mockito.when(methodCall).thenAnswer(answer)) 预期回调接口生成期望值
Mockito.doAnswer(answer).when(methodCall).[method] 预期回调接口生成期望值(直接执行不判断)
Mockito.spy(Object) 用spy监控真实对象,设置真实对象行为
Mockito.doNothing().when(mock).[method] 不做任何返回
Mockito.doCallRealMethod().when(mock).[method] //等价于Mockito.when(mock.[method]).thenCallRealMethod(); 调用真实的方法
reset(mock) 重置mock

实例代码:

@RunWith(SpringRunner.class)		//Runner 来运行你的测试代码
//classes属性指定启动类,WebEnvironment.RANDOM_PORT随机生成一个端口号
@SpringBootTest(classes = XXXApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@FixMethodOrder(MethodSorters.NAME_ASCENDING) //按照方法名字顺序执行
@ActiveProfiles(value = "test")		//声明在为测试类加载ApplicationContext时应使的定义配置文件
public class MockitoXXXServiceTest {
     

  @MockBean
  private AService aService;

  @InjectMocks						//创建一个实例,类中用@Mock(或@Spy)注解创建的mock将被注入到用该实例中
  @Resource							//本例mock出来的AService将会被注入到XXXService中
  private XXXService xXXService;

  // 注意这两个都是静态方法,所有测试方法执行前执行一次,所有测试方法后执行一次
  @BeforeClass
  public static void setUpClass(){
     }
  @AfterClass
  public static void destroyClass(){
     }
  
  //下面两个每一个test运行前后各执行一次
  @Before							
  public void setUp() {
     }
  @After
  public void destroy() {
     }

  @Test(timeout = 1000)				//测试方法执行超过1000毫秒后算超时,测试将失败
  public void test_timeout(){
     }

  @Ignore("ignore this test") 		//执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类
  public void test_ignore(){
     }

  @Test								//
  public void test_copy_1() {
     
    Mockito.when(accountService.getCurrTenant()).thenReturn("TDH");
    Mockito.when(accountService.getCurrUsername()).thenReturn("admin");

    String source = UUID.randomUUID().toString();
    String dest = UUID.randomUUID().toString();

    AssignmentDetail detail = TestUtil.detail();
    detail.setUuid(source);

    assignmentService.save(detail);
    assignmentService.copy(source, dest);

    AssignmentDetail result = assignmentService.getDetail(dest);
    assertThat(result.getUuid(), equalTo(dest));

    result.setUuid(source);
    result.setName(detail.getName());
    assertThat(detail.equalsContent(result), is(true));

    assignmentService.delete(source);
    assignmentService.delete(dest);
  }

  @Test
  public void test_create_1() {
     
    try {
     
      assignmentService.create(null);
    } catch (QualityException e) {
     
      assertThat(e.getErrorCode().getErrorCode(), is(ErrorCode.ASSIGNMENT_CREATE_ERROR.getErrorCode()));
      return;
    }
    assertThat(null, notNullValue());
}

  @Test
  public void test_create_2() {
     
    try {
     
      assignmentService.create("");
    } catch (QualityException e) {
     
      assertThat(e.getErrorCode().getErrorCode(), is(ErrorCode.ASSIGNMENT_CREATE_ERROR.getErrorCode()));
      return;
    }
    assertThat(null, notNullValue());
  }

  @Test
  public void test_create_3() {
     
    Mockito.when(nameService.getName(Mockito.any(NameRequest.class))).thenReturn("name");
    boolean b = assignmentService.create(uuid);
    assertTrue(b);
    assignmentService.delete(uuid);
  }

  /*
  *  Test generateLogicalModeContent()
  * */
  @Test
  public void test_4() {
     
    Mockito.when(ruleDAO.getLMRuleInfos(Mockito.any())).thenReturn(TestUtil.rulepos());
    Mockito.when(nameService.getName(new NameRequest(Mockito.any(String.class), ""))).thenReturn("");
    Mockito.when(lmDAO.getLMTemplateInfo(Mockito.any())).thenReturn(TestUtil.templates());
    AssignmentLogicalModelContent content =
        assignmentService.generateLogicalModeContent(entity);

  }

  @Test//测试uuid、survivor、survivor.id存在的情况
  public void test_deploy_2(){
     
    final String uuid = UUID.randomUUID().toString();
    assignmentDAO.createAssignment(new Assignment(uuid,"name"));
    AssignmentDetail assignmentDetailByAssignmentUuid = assignmentDAO.getAssignmentDetailByAssignmentUuid(uuid);
    AssignmentLogicalModel logicalModel = new AssignmentLogicalModel.Builder()
            .version(ScheduleVersion.RELEASE.name())
            .assignmentId(assignmentDetailByAssignmentUuid.getId())
            .flowUuid(UUID.randomUUID().toString())
            .id(123L)
            .build();
    Mockito.when(lmDAO.getByAssignmentIdAndVersion(Mockito.any(Long.class), Mockito.any(String.class))).thenReturn(logicalModel);
//    QualityWorkflowService qualityWorkflowService = mock(QualityWorkflowService.class);
    doNothing().when(workflowService).retireFlow(Mockito.anyString());
    doNothing().when(workflowService).updateScheme(Mockito.any(AssignmentLogicalModel.class),Mockito.anyString());
    doNothing().when(lmDAO).softCreate(Mockito.anyLong());
    assignmentService.deploy(uuid);
    assignmentDAO.remove(uuid);
  }

  @Test//测试uuid、survivor存在、survivor.id不存在的情况
  public void test_deploy_3(){
     
    final String uuid = UUID.randomUUID().toString();
    assignmentDAO.createAssignment(new Assignment(uuid,"name"));
    AssignmentDetail assignmentDetailByAssignmentUuid = assignmentDAO.getAssignmentDetailByAssignmentUuid(uuid);
    AssignmentLogicalModel logicalModel = new AssignmentLogicalModel.Builder()
            .version(ScheduleVersion.RELEASE.name())
            .assignmentId(assignmentDetailByAssignmentUuid.getId())
            .flowUuid(UUID.randomUUID().toString())
            .build();
    Mockito.when(lmDAO.getByAssignmentIdAndVersion(Mockito.any(Long.class), Mockito.any(String.class))).thenReturn(logicalModel);
    Mockito.when(workflowService.createScheme(Mockito.any(AssignmentLogicalModel.class))).thenReturn("");
    doNothing().when(lmDAO).updateLogicModelFlowUuidById(Mockito.anyLong(),Mockito.anyString());
    doNothing().when(workflowService).deployFlow(Mockito.anyString());
    assignmentService.deploy(uuid);
    assignmentDAO.remove(uuid);
  }


//  @Test//测试QUOTATION
//  public void test_asyncSchedule_2(){
     
//    try {
     
//      final String uuid = UUID.randomUUID().toString();
//      assignmentDAO.createAssignment(new Assignment(uuid,uuid));
//      Mockito.when(lmDAO.getByAssignmentIdAndVersion(Mockito.anyLong(),Mockito.anyString()))
//              .thenReturn(new AssignmentLogicalModel.Builder().id(1234L).build());
//      Mockito.when(schedulerExplorer.scheduler(Mockito.any(AssignmentLogicalModel.class))).thenReturn();//如何返回接口类?
//      Scheduler scheduler = Mockito.mock(Scheduler.class);
//      Mockito.doNothing().when(scheduler).createSchema();
//      HashMap jobIds = new HashMap<>();
//      Mockito.when(scheduler.prepare(Mockito.anyLong(),Mockito.any(OpsScheduleMode.class))).thenReturn(new OpsJobTaskIds(1234L,jobIds));
//      Mockito.doNothing().when(scheduler).schedule(Mockito.any(OpsJobTaskIds.class));
//
//      assignmentService.asyncSchedule(uuid,ScheduleVersion.QUOTATION,123L);
//    } catch (QualityException e) {
     
//      assertThat(e.getErrorCode().getErrorCode(),is(ErrorCode.UNKNOWN_QUALITY_SERVER_ERROR_ARGS.getErrorCode()));
//    }
//  }

  @Test
  public void test_retire_1(){
     
    List<String> uuids = new ArrayList<>();
    uuids.add(UUID.randomUUID().toString());
    uuids.add("654321");
    Mockito.when(lmDAO.getByUuidAndVersion(Mockito.any(String.class),Mockito.any(ScheduleVersion.class)))
            .thenReturn(new AssignmentLogicalModel.Builder().flowUuid(UUID.randomUUID().toString()).build());
    assignmentService.retire(uuids);
  }
}

参考文章:https://www.jianshu.com/p/ecbd7b5a2021

3 升级版

注意:以下需要用到PowerMockito的需要引入依赖:

     <dependency>
         <groupId>org.mockitogroupId>
         <artifactId>mockito-allartifactId>
         <scope>testscope>
     dependency>
     <dependency>
         <groupId>org.powermockgroupId>
         <artifactId>powermock-coreartifactId>
         <scope>testscope>
     dependency>
     <dependency>
         <groupId>org.powermockgroupId>
         <artifactId>powermock-api-mockitoartifactId>
         <scope>testscope>
     dependency>

MOCK静态方法

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class Test {
     
  @InjectMocks
  @Resource
  private B b = new B();
  
  @Test(expected = IOException.class)
  public void testIOException() {
     
   PowerMockito.mockStatic(A.class);
   PowerMockito.when(A.method()).thenThrow(new IOException());
   b.service();
   }
}

你可能感兴趣的:(软件测试,单元测试,mockito)