文章目录
  1. 1. 单元测试
    1. 1.0.1. 单独测试access层,跳过business和resource层
    2. 1.0.2. 单独测试business层,跳过resource层
    3. 1.0.3. 单独测试resource层,跳过直接访问数据库
  • 2. 集成测试
  • 写测试用例时,如果只关注输入、输出或是否被调用,建议使用Mock框架,能使用Mock的框架有EasyMock、Mockito、PowerMock、JMock等;

    Mock框架在处理”黑洞”接口,有特别的效果,

    下面来分享下Mockito框架的使用:

    假如说我现在项目有三层,

    • 第一层是入口层,我把它叫做”access”;
    • 第二层是业务处理层,我把它叫做”business”;
    • 第三层是数据处理层,我把她叫做”resource”;

    单元测试

    是指对软件中的最小可测试单元进行检查和验证。

    现在我分情况来说明一下怎么利用Mockito框架去进行Mock测试;

    单独测试access层,跳过business和resource层

    只需要把business层Mock掉就可以了,因为resource层是有business层去调用,所以不必理会,下面上例子:

    import io.grpc.StatusRuntimeException;
    import io.grpc.stub.StreamObserver;
    import org.mockito.ArgumentCaptor;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.BeforeMethod;
    import org.testng.annotations.Test;
    import java.util.Date;
    import static org.mockito.Matchers.anyInt;
    import static org.mockito.Mockito.*;
    
    public class ServiceAccessTest {
    private  int customerId = 2;
    private int invalidCustomerId =0;
    
    @Mock
    private DemoBusiness demoBusiness; //需要Mock的business层
    
    @Mock
    private StreamObserver<DemoResponse> demoSO;
    
    @InjectMocks
    DemoServiceAccess demoServiceAccess;//需要测试的access层
    
    //跑测试前要进行的初始化
    @BeforeMethod
    public void setup() {
        demoServiceAccess = new DemoServiceAccess();
        MockitoAnnotations.initMocks(this);
    }
    
    //测试跑完后需要做的事情
    @AfterMethod
    public void after() {
        reset(demoBusiness, demoSO);
        reset(demoBusiness, helpDemoSO);
        reset(demoBusiness, getDemoLogSO);
    }
    
    @Test
    public void DemoTest_Success() {
        DemoBusinessPojo demoPojo = new DemoBusinessPojo();
        demoPojo.setContinueDays(5);
        demoPojo.setIncreaseScore(5);
        demoPojo.setLastTime(new Date().getTime());
        demoPojo.setTotalTimes(11);
        when(demoBusiness.summit(customerId)).thenReturn(demoPojo);
    
        ArgumentCaptor<DemoResponse> ac = ArgumentCaptor.forClass(DemoResponse.class);
        demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
        verify(demoSO).onNext(ac.capture());
        reset(demoBusiness);
    }
    
    @Test(expectedExceptions = InvalidArgumentException.class)
    public void DemoFailTest() {
        demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(invalidCustomerId).build(), demoSO);
    }
    
    @SuppressWarnings("unchecked")
    @Test(expectedExceptions = StatusRuntimeException.class)
    public void DemoFailTest1() {
        when(demoBusiness.summit(customerId)).thenThrow(ResourceUnavailableException.class);
        demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
    }
    
    @SuppressWarnings("unchecked")
    @Test(expectedExceptions = Exception.class)
    public void DemoFailTest2() {
        when(demoBusiness.summit(customerId)).thenThrow(Exception.class);
        demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
    }
    

    单独测试business层,跳过resource层

    因为是单元测试,所以之前的access层我们也不必去理会了,从而只Mock层就OK了,下面上例子:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.TestPropertySource;
    import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
    import org.testng.annotations.Test;
    import java.util.Date;
    import java.util.concurrent.atomic.AtomicInteger;
    import static org.assertj.core.api.Assertions.assertThat;
    
    
    @ProfileTest
    @ProfileDevelop //环境为dev
    @ContextConfiguration(classes = {DemoBusiness.class})//加载类,如果有多个类,可以用","隔开,往后添加
    @TestPropertySource(value = "classpath:application.properties")//加载配置文件
    public class DemoBusinessTest extends AbstractTransactionalTestNGSpringContextTests {
    
        @Autowired
        private DemoBusiness demoBusiness;//需要测试的business层
    
    
        @Autowired
        private DemoResources demoResources;//需要Mock层
    
        @Test
        public void demoNormal() {
            long helpCustomerId = 111;
            long customerId = 100;
            DemoBusinessPojo demoPojo = new DemoBusinessPojo();
            demoPojo.setContinueDays(5);
            demoPojo.setIncreaseScore(5);
            demoPojo.setLastTime(new Date().getTime());
            demoPojo.setTotalTimes(11);
            //如果传过去的对象或者是参数,而在方法后面又进行重新new了一个新的对象或者参数,那么我们应该传进去的是任何的对象或者参数,
            比如说,customerId传进去,但是真正到达demoBusiness.summit()里面,customerId的值动态变化,那么我们就应该
            //when(demoResources.summit(any(customerId))).thenReturn(demoPojo);//Mock层
            when(demoResources.summit(customerId)).thenReturn(demoPojo);//Mock层
    
            DemoBusinessPojo demoBusinessPojo = demoBusiness.summit(customerId,
                    101, helpCustomerId);//测试层
    
            assertThat(demoBusinessPojo.getIncreaseScore()).isGreaterThanOrEqualTo(1);
            assertThat(demoBusinessPojo.getContinueDays()).isGreaterThanOrEqualTo(1);
            assertThat(demoBusinessPojo.getLastTime()).isGreaterThan(1);
            assertThat(demoBusinessPojo.getTotalTimes()).isGreaterThanOrEqualTo(1);
        }
    }
    

    单独测试resource层,跳过直接访问数据库

    由于到这层是需要直接访问数据库的,所以我们需要直接Mock数据库了,下面上例子:

    有待完善……

    集成测试

    在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试。

    有待完善……

    文章目录
    1. 1. 单元测试
      1. 1.0.1. 单独测试access层,跳过business和resource层
      2. 1.0.2. 单独测试business层,跳过resource层
      3. 1.0.3. 单独测试resource层,跳过直接访问数据库
  • 2. 集成测试