美文网首页软件测试
单元测试小结

单元测试小结

作者: 某某程序员_ | 来源:发表于2017-10-16 19:13 被阅读0次

    1. 简单逻辑测试,纯本地测试,不涉及数据库以及远程调用

    源码:

    public class EmailValidate {
    
        public static boolean validate(String s) {
            String regex = "^\\w+([-_.]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,6})+$";
            if (s == null || s.matches(regex)){
                return true;
            }else {
                return false;
            }
        }
        
    }
    

    assertTrue表示期望结果正确,否则抛出异常
    assertFalse表示期望结果错误,否则抛出异常

    @Test
    public void testValidate(){
        String email = "wqwq@qq.com";
        //如果邮箱正确,则不会输出异常信息,
        Assert.assertTrue("邮件格式错误",EmailValidate.validate(email));
        //如果邮箱正确,输出异常信息,
        Assert.assertFalse("邮件格式正确", EmailValidate.validate(email));
    }
    

    测试结果:

    java.lang.AssertionError: 邮件格式正确
    
        at org.junit.Assert.fail(Assert.java:88)
        at org.junit.Assert.assertTrue(Assert.java:41)
        at org.junit.Assert.assertFalse(Assert.java:64)
        at com.rongzhijia.auth.api.validate.core.EmailValidateTest.testValidate(EmailValidateTest.java:18)
    Process finished with exit code -1
    
    @Test
    public void testValidate(){
        String email = "@qq.com";
        //如果邮箱错误,不会输出异常信息
        Assert.assertFalse("邮件格式正确", EmailValidate.validate(email));
        //如果邮箱错误,输出异常信息
        Assert.assertTrue("邮件格式错误",EmailValidate.validate(email));
    }
    

    测试结果:

    java.lang.AssertionError: 邮件格式错误
    
        at org.junit.Assert.fail(Assert.java:88)
        at org.junit.Assert.assertTrue(Assert.java:41)
        at com.rongzhijia.auth.api.validate.core.EmailValidateTest.testValidate(EmailValidateTest.java:18)
        ...
    Process finished with exit code -1
    
    

    2. 涉及到数据库访问的测试(此处使用spring框架)

    2.1 spring 配置文件加载

    maven

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${springframework.version}</version>
                <scope>compile</scope>
            </dependency>
    

    直接使用项目中的文件,修改一下数据库配置即可。我喜新建一个BaseTest类,这样就不用每个单元测试类都进行如下配置,直接继承即可。
    @RunWith(SpringJUnit4ClassRunner.class):SpringJUnit4ClassRunner在spring-test jar包下,此注解集成了Spring以及junit组件
    @ContextConfiguration: 加载配置文件
    @Transactional: 如果有初始化数据,加上此注解在执行完单元测试之后自动回滚
    @Ignore: 如果环境不跑测试用例,使用此注解忽略掉

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath*:/test/spring/*.xml")
    @Transactional
    //@Ignore
    public class BaseTest {
    }
    

    具体测试类
    如果要忽略测试用例,则此类也要加上注解: @Ignore

    2.2 测试用例编写

    2.2.1 没有初始化数据,直接使用db里面的数据,这个可能会出现数据问题。

    //@Ignore
    public class UserManageServiceTest extends BaseTest{
    
        @Autowired
        private UserManageService userManageService;
    
        @Test
        public void updateUserResourcesTest(){
            try{
                UserResourceBo userResourceBo = new UserResourceBo();
                userResourceBo.setAuthAccountId(12);
                List r = Arrays.asList(1,2,3,4,24,25,26,27,28,29,30,31,32,33,34,35,36);
                userResourceBo.setAuthResourceIdList(r);
                userManageService.updateUserResources(userResourceBo);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    

    测试结果:原来测试的数据已经找不到,报错。

    2017-10-16 14:22:14,867 ERROR com.auth.service.impl.UserManageServiceImpl [main] - 
    com.auth.common.exception.AuhtServiceException: 账户不存在
    

    2.2.2 自己初始化数据,使用自己的数据

    private AuthAccount authAccount = new AuthAccount();
    @Before
    public void init(){
        authAccount.setRoleId(1);
        authAccount.setInstitutionUsername("utest@1.com");
        authAccount.setAccountName("utest@1.com");
        userManageService.addUser(authAccount);
    }
    
    @Test
    public void updateUserResourcesTest1(){
        try{
            UserResourceBo userResourceBo = new UserResourceBo();
            userResourceBo.setAuthAccountId(authAccount.getId());
            List r = Arrays.asList(1,2,3,4,24,25,26,27,28,29,30,31,32,33,34,35,36);
            userResourceBo.setAuthResourceIdList(r);
            userManageService.updateUserResources(userResourceBo);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    

    测试结果, 没有异常,测试成功。

    ...
    Disconnected from the target VM, address: '127.0.0.1:8429', transport: 'socket'
    
    Process finished with exit code 0
    
    

    2.2.3 以上测试看起来并没有验证什么,仅仅方法成功调用。下面将预期数据与实际结果做出对比,准确的看到测试效果。

    @Test
    public void updateUserResourcesTest1(){
        try{
            UserResourceBo userResourceBo = new UserResourceBo();
            Assert.assertNotNull(authAccount.getId());
            userResourceBo.setAuthAccountId(authAccount.getId());
            List r = Arrays.asList(1,2,3,4,24,25,26,27,28,29,30,31,32,33,34,35,36);
            List r2 = Arrays.asList(1,2,3,4,24,25,26,27,28,29,30,31,32,33,34,35);//用来对比的数据
            userResourceBo.setAuthResourceIdList(r);
            userManageService.updateUserResources(userResourceBo);//将相关数据更新进去
            //查询出刚更新的数据,抽取出ResourceId列表
            List r1 = authRoleResourceService.getAuthRoleResourceListByRoleId(authAccount.getRoleId())
                            .stream().map(authRoleResource -> authRoleResource.getResourceId()).collect(toList());
            //打印对比结果,此处初始化的数据与查询的数据相同,表示更新成功
            Assert.assertArrayEquals(r.toArray(), r1.toArray());
            //用以对比的结果,r和r2明显不一样,应该抛出异常
            Assert.assertArrayEquals(r.toArray(), r2.toArray());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    

    测试结果,可以看出,符合预期要求。


    image.png

    3. 外部API测试

    还有一种测试场景,测试外部API,因为外部服务不能保证一直都是可用的,同时,如果切换环境之后,也许有因为权限等访问不了的情况。引入测试框架mockito,不依赖外部服务,只要和外部服务约定好相关数据结构即可。

    maven

            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>2.11.0</version>
            </dependency>
    

    3.1 简单的外层方法调用:

        public class LoanChannelReadServiceTest {
    
        private LoanChannelReadService loanChannelReadService;
    
        @Test
        public void testGetLoanChannelByChannelID(){
            //mock 调用类
            loanChannelReadService = mock(LoanChannelReadService.class);
    
            //设置mock结果
            LoanChannelDTO mockResult = new LoanChannelDTO();
            mockResult.setId(111);
            mockResult.setChannelType("test");
    
            //设定mock规则,当when里面的方法调用时,返回thenReturn里面的结果
            when(loanChannelReadService.getLoanChannelByChannelID(anyInt())).thenReturn(mockResult);
    
            //具体调用
            LoanChannelDTO loanChannelDTO = loanChannelReadService.getLoanChannelByChannelID(111);
            //执行结果对比
            Assert.assertEquals(mockResult.getId(), loanChannelDTO.getId());
        }
    }
    

    测试结果,通过。

    Process finished with exit code 0
    

    3.2 ,进一步的测试调用方法内部细节:

        //内部调用类使用此常规注解即可
        @Mock
        private LoanChannelReadService loanChannelReadService;
    
        //调用类使用此注解,且new一个对象
        @InjectMocks 
        private UserAccountService userAccountService = new UserAccountServiceImpl();
    
        @Before
        public void init(){
            //将内部调用类注入到 调用类
            MockitoAnnotations.initMocks(this);
        }
        @Test
        public void testGetLoanChannelByChannelIDInnner() throws Exception{
            //设置mock结果
            LoanChannelDTO mockResult = new LoanChannelDTO();
            mockResult.setId(111);
            mockResult.setChannelType("test");
    
            //设定mock规则,当when里面的方法调用时,返回thenReturn里面的结果
            when(loanChannelReadService.getLoanChannelByChannelID(anyInt())).thenReturn(mockResult);
    
            LoanChannelDTO loanChannelDTO = userAccountService.getLoanChannelById(111);
            //验证内部调用类的方法是否执行
            verify(loanChannelReadService).getLoanChannelByChannelID(111);
            //验证执行结果是否正确
            Assert.assertEquals(mockResult.getId(), loanChannelDTO.getId());
        }
    

    测试结果,结果符合预期。

    ...
    configuration as safe fallback point
    Disconnected from the target VM, address: '127.0.0.1:10951', transport: 'socket'
    
    Process finished with exit code 0
    

    相关文章

      网友评论

        本文标题:单元测试小结

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