软件测试

单元测试小结

2017-10-16  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读