java 单元测试

1.1 单元测试定义

单元测试(Unit Test,以下简称UT)是编写测试代码,用以检测特定的、明确的、细颗粒度的功能,UT只针对功能点进行测试,一般不包括对业务流程正确性的测试。

1.2 单元测试的意义

(1) UT可以很好的保证代码质量,增加开发人员的信心。

(2) UT可以一定程度提高代码合理性。当我们发现给某一个方法写UT很困难时,比如需要覆盖的分支特别多,那可能说明该方法是可以拆分的;又比如说给某个方法写单测时需要mock的调用十分多,说明该方法违背了单一责任原则,即一个方法只处理一个逻辑做一件事,处理了太多的逻辑,需要进行拆分。

(3) UT能够有效防止回溯问题的出现,即出现之前版本没有而新版本才出现的问题。这种问题的严重程度是最高的,影响也是最恶劣的。因为一般用户可以接受在老版本中本就不存在的功能不可用,但很难接受一个在老版本中用得好好的功能在新版本中突然失效了。在新功能开发后,运行之前的UT,如果发现了未变更逻辑的老功能UT报错,则很有可能是出现了回溯问题。

(4) UT能够帮助开发测试人员确定回归范围。

1.3 单元测试的规范

(1)可衡量,UT 通过率要求100%,行覆盖率要求50%以上。如果有任何一个UT不通过,不是单元测试有问题,就是代码逻辑有问题;覆盖率可以根据具体功能进行挑战,一般不低于40%,通常,越底层的代码覆盖率应该越高,越新的代码覆盖率也应该越高,当代码逻辑变更时,对应的UT 也应该做相应的更改。

(2)独立性:UT之间应该是独立且相互隔离的,一个单元测试只测试一个方法。

(3)对实现类进行测试而非接口,面向接口编程,但面向实现测试

(4)私有方法通过调用类的单测进行测试。私有方法在测试类内没法直接调用,除非使用反射或其他Mock框架(PowerMock, TestableMock等)

(5)在单测中禁止使用try-catch

1.4 单元测试常用注解

@BeforeClass    全局只会执行一次,而且是第一个运行

@Before        在测试方法运行之前运行

@Test          测试方法

@After         在测试方法运行之后允许

@AfterClass     全局只会执行一次,而且是最后一个运行

@Ignore        忽略此方法

1.5 MAVEN 依赖

        <dependency>

            <groupId>org.mockito</groupId>

            <artifactId>mockito-core</artifactId>

            <version>2.8.47</version>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.powermock</groupId>

            <artifactId>powermock-api-mockito2</artifactId>

            <version>1.7.4</version>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.powermock</groupId>

            <artifactId>powermock-module-junit4</artifactId>

            <version>1.7.4</version>

            <scope>test</scope>

        </dependency>

 

1.6 DEMO

import junit.framework.TestCase;

import org.junit.Test;

 

public class AvGroupCustomerTest extends TestCase {

       @Test

       public void test () {

              AvGroupCustomer avg = new AvGroupCustomer();

              avg.setDescription("wde0");

              avg.getValidTime();

assertTrue(true);

       }

 

import com.envision.wind.dimension.management.externalrest.domain.Asset;

import com.envision.wind.dimension.management.externalrest.service.RedisCacheService;

import com.envision.wind.dimension.management.externalrest.service.dao.AssetMapper;

import junit.framework.TestCase;

import org.junit.Test;

import org.mockito.InjectMocks;

import org.mockito.Mock;

import org.mockito.MockitoAnnotations;

import java.util.ArrayList;

import java.util.List;

import static org.mockito.ArgumentMatchers.anyInt;

import static org.mockito.ArgumentMatchers.anyString;

import static org.powermock.api.mockito.PowerMockito.doNothing;

import static org.powermock.api.mockito.PowerMockito.when;

 

public class AssetServiceImplTest extends TestCase {

    @Mock

    private AssetMapper mapper;

    @Mock

    private RedisCacheService redisCacheService;

    @InjectMocks

    private AssetServiceImpl impl;

    @Test

    public void testAgcMappingServiceImplTest() {

        MockitoAnnotations.initMocks(this);

        when(redisCacheService.getValueByRedisKey(anyString())).thenReturn(null);

        List<Asset> objectList =  new ArrayList<>();

        when(mapper.selectAll()).thenReturn(objectList);

doNothing().when(redisCacheService).saveValueInRedis(anyString(),anyString(),anyInt());

        impl.loadAll("customerId");

        when(mapper.selectByPrimaryKey(anyString())).thenReturn(new Asset());

        impl.loadDomainById("customerId","id");

        assertTrue(true);

    }

}

上一篇:JDBC:ResultSet


下一篇:读取application.properties参数注入到Bean属性