首先问一个问题,在接口测试中,验证被测接口的返回值是否符合预期是不是就够了呢?
场景
转账是银行等金融系统中常见的一个场景。在在最近的一个针对转账服务的单元测试中,笔者就遇到了上述问题。一个极端简化的转账申请如下图:
在一个B端用户通过转账服务接口发起转账申请后,转账服务接口在完成发起转账申请的过程中,在完成各项合法性校验,确定可以发起转账时,会从外部流水号服务那里申请到一个全局唯一且单调递增的流水号,该流水号将作为转账申请提交成功的返回值向申请方返回。同时,该流水号将作为转账申请记录的一部分,写入后台数据库等待后续审核。
从上述介绍中,我们得以了解到,这里的转账服务接口只是完成了申请的接收工作。转账申请需要后续被人工审核后才能完成实际的转账。
实现伪代码
public class EntryRepository { ... public void save(Entity entity) { System.out.println(entity.getFlowNo); } } @Service public class EntryService throws Exception{ @Autowired private EntryRepository entryReposity; @Autowired private FlowNoService flowNoService; @Transactional public String submit(Entity entity) { validEntity(entity); entity.setFlowNo(flowNoService.getNextFlowNo()); //流水号 entity.setStatus("SUBMITTED"); //已提交 entryReposity.save(entity); return entity.getFlowNo(); } } |
以上是一个极简的代码实现逻辑,完成了申请单检查、流水号获取、数据库保存以及接口返回。
第一个单元测试- 请求/返回
public class EntryServiceTest { @InjectMocks private EntryService entryService; @Mock private EntryRepository entryReposity; @Mock private FlowNoService flowNoService; @Test public void shouldReturnFlowNo(){ Entity entity= new entity; entity.setAmount("一个亿"); String flowNo="20200307000001"; Mockito.when(flowNoService.getNextFlowNo()).thenReturn(flowNo); assertThat(entryService.submit(entity)).isEqualTo(flowNo); } } |
第一个用例首先验证了接口的返回值。
第二个单元测试-写库
@Captor private ArgumentCaptor<Entity> captor; @Test public void shouldCapture() { Entity entity= new entity; entity.setAmount("一个亿"); String flowNo="20200307000001"; Mockito.when(flowNoService.getNextFlowNo()).thenReturn(flowNo); Mockito.verify(entryReposity,times(1)).save(captor.capture()); Entity captured= captor.getValue(); Entity expected= new Entity(); expected.setFlowNo(flowNo); expected.setStatus("SUBMITTED"); assertThat(captured).isEqualToComparingOnlyGivenFields(expected,"flowNo","status"); } } |
在之前的测试用例类中,我们再添加第二个单元测试用例,来验证数据库写库的数据是否符合预期结果。
第三个用例 -- 两笔申请?
如何对两笔申请进行单元测试,Mock又如何写?这个就留给读者自行练习了。
如果不是写库,而是通过MQ对外发布?又如何进行测试呢?
小结
本案例演示了如何使用Mockito提供的Capture特性来验证方法的传参,同时也展示了如何使用AssertJ进行对象的多个属性的断言。
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。