0
点赞
收藏
分享

微信扫一扫

Java怎样单测void类型的方法?

得一道人 2023-02-07 阅读 138


Java的Sevice层会有很多void类型的方法,比如save*、update*,这类方法只是做一些更新,不会有返回值,其单测不能根据方法的返回值来编写,只能采用特殊方法;

本方法环境:Mockito、testng

被测试的方法:



想要被测试的VOID方法

Java



@Override public void updateRuleName(Long ruleId, String newRuleName, Long ucId) { Assert.notNull(ruleId, "规则ID不能为Null"); Assert.notNull(newRuleName, "规则名称不能为Null"); Assert.notNull(ucId, "操作人的UCID不能为Null"); String cleanNewRuleName = StringUtils.trim(newRuleName); if (StringUtils.isBlank(cleanNewRuleName)) { throw new IllegalArgumentException("新的规则名称不能为空"); } // 查询规则对象 Rule rule = queryRuleById(ruleId); if (null == rule) { throw new IllegalDataException("没有查到该规则"); } rule.setRuleId(ruleId); rule.setRuleName(cleanNewRuleName); rule.setUpdateUcid(ucId); rule.setUpdateTime(new Date()); ruleDao.updateSelective(rule); }


CREATE TABLE `tcc` (
`idx` INT(11),
`typeid` INT(11),
`value1` INT(11),
`value2` INT(11),
UNIQUE KEY(idx, typeid)
) ENGINE = INNODB DEFAULT CHARSET =utf8;

-- 第一条SQL的执行,会新增一条数据,本SQL多次执行,效果相同,因为后续的操作,变成了UPDATE
INSERT INTO tcc (idx, typeid, value1)
VALUES (1,2,3) ON DUPLICATE KEY UPDATE value1 =3;

-- 第二条SQL直接进行UPDATE,把新列的值update进去
INSERT INTO tcc (idx, typeid, value2)
VALUES (1,2,4) ON DUPLICATE KEY UPDATE value2 =4;



测试的方法:



void返回的方法测试






Java



@Test public void testUpdateRuleName() { Long ruleId = 1L; String newRuleName = "newRuleName"; Long ucId = 123L; List<Rule> rules = new ArrayList<Rule>(); Rule rule = new Rule(); rule.setRuleStatus((byte) DBValueSetting.RULE_STATUS_TAKE_EFFECT); rules.add(rule); // 查询规则对象 Map<String, Object> params = new HashMap<String, Object>(); params.put("ruleId", ruleId); Mockito.when(ruleDao.queryRulesByCondition(params)).thenReturn(rules); Mockito.doAnswer(new Answer<Object>() { public Object answer(InvocationOnMock invocation) { // 断点2:这里随后执行 Rule rule = (Rule) invocation.getArguments()[0]; Assert.assertTrue(rule.getRuleName().equals("newRuleName")); return null; } }).when(ruleDao).updateSelective(Mockito.any(Rule.class)); // 断点1:先执行到这里 ruleService.updateRuleName(ruleId, newRuleName, ucId); }


@Test
public void testUpdateRuleName ( ) {
Long ruleId = 1L ;
String newRuleName = "newRuleName" ;
Long ucId = 123L ;

List <Rule> rules = new ArrayList <Rule> ( ) ;
Rule rule = new Rule ( ) ;
rule . setRuleStatus ( ( byte ) DBValueSetting . RULE_STATUS_TAKE_EFFECT ) ;
rules . add ( rule ) ;

// 查询规则对象
Map < String , Object > params = new HashMap < String , Object > ( ) ;
params . put ( "ruleId" , ruleId ) ;
Mockito . when ( ruleDao . queryRulesByCondition ( params ) ) . thenReturn ( rules ) ;

Mockito . doAnswer ( new Answer <Object> ( ) {
public Object answer ( InvocationOnMock invocation ) {
// 断点2:这里随后执行
Rule rule = ( Rule ) invocation . getArguments ( ) [ 0 ] ;
Assert . assertTrue ( rule . getRuleName ( ) . equals ( "newRuleName" ) ) ;
return null ;
}
} ) . when ( ruleDao ) . updateSelective ( Mockito . any ( Rule . class ) ) ;

// 断点1:先执行到这里
ruleService . updateRuleName ( ruleId , newRuleName , ucId ) ;
}



如注释所示,如果加了两个断点的话,执行的过程中,会先执行最后的调用行,端点1执行的过程中,会执行到端点2的stub,这时候在断点2可以获取到方法执行的入参,对入参进行Assert校验,即可实现目的;

new Anwer是个接口,其中只有一个方法,用于设置方法调用的代理执行入口



doAnswer的实现






Java



public interface Answer<T> { /** * @param invocation the invocation on the mock. * * @return the value to be returned * * @throws Throwable the throwable to be thrown */ T answer(InvocationOnMock invocation) throws Throwable; }


public interface Answer <T> {
/**
* @param invocation the invocation on the mock.
*
* @return the value to be returned
*
* @throws Throwable the throwable to be thrown
*/
T answer ( InvocationOnMock invocation ) throws Throwable ;
}
————————————————



当代码执行到“ruleDao.updateSelective(rule);”的时候,会触发针对mock对象调用的拦截器,在拦截器中,会创建一个动态代理,动态代理的invocation就是new Answer中覆盖的方法;

使用拦截、代理两种方法,实现了对mock对象方法的入参、出参的设定和获取,使用这种方式,就可以校验VOID方法内部的执行类调用的情况;

 

 

举报

相关推荐

0 条评论