单元测试小结
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