其实,这两段代码并没有什么分支,要大费周张地测试有些多余。最好能够在满足覆盖率的情况下只测试order,尽可能减少所谓的“service”。利用Command模式,将“service”压缩到一个。
Java代码
@Test @Test |
经过修改后,在测试中我们不用再编写样板代码(同时产品代码中也不用了),由于Order、Command都可以通过构造函数实例化, 测试场景的准备就简单了。而且@Transactional忘记添加的问题也有所缓解(因为只需要一个“service”了)
四、对应代码抽象级别的测试
Java代码
public void run() { loggingSupport.info("start running, productId=" + productId); if (a) { ...... } else if (b) { ...... } else { ...... } loggingSupport.info("end running, productId=" + productId); } |
在它的三个测试中,都需要特意指定一下日志记录的内容:
Java代码
final String startText = "start running, productId" + productId; context.checking(new Expectations() { |
出现这种情况的一个原因就是抽象层级没有把握好,在run()方法中,应该是关注的流程,而不是流程节点的实现。比如你在一个测试中编写了很多的断言(对模拟对象的预期定义也可以看作是一种断言),就很有可能说明了这种现象,最好通过引入更细粒度的对象来分担职责。这里我们不妨引入RunnerNotifer,让它来通知记录日志:
Java代码
public void run() {
|
这样修改之后,测试代码就不需要再拼接日志内容了:
Java代码
context.checking(new Expectations() { { oneOf(runnerNotifier).notifyStart(productId); // other expectations oneOf(runnerNotifier).notifyEnd(productId); } }); target.run(); |
然后再单独为RunnerNotifier的实现添加测试即可。
本次就到这里。