链式调用的模拟或存根

新手上路,请多包涵
protected int parseExpire(CacheContext ctx) throws AttributeDefineException {
    Method targetMethod = ctx.getTargetMethod();
    CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);
    ExpireExpr cacheExpire = targetMethod.getAnnotation(ExpireExpr.class);
    // check for duplicate setting
    if (cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE && cacheExpire != null) {
        throw new AttributeDefineException("expire are defined both in @CacheEnable and @ExpireExpr");
    }
    // expire time defined in @CacheEnable or @ExpireExpr
    return cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE ? cacheEnable.expire() : parseExpireExpr(cacheExpire, ctx.getArgument());
}

那是测试的方法,

 Method targetMethod = ctx.getTargetMethod();
CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);

我必须模拟三个 CacheContext、Method 和 CacheEnable。有什么想法可以使测试用例更简单吗?

原文由 jilen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 382
2 个回答

Mockito 可以处理链式存根

 Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

// note that we're stubbing a chain of methods here: getBar().getName()
when(mock.getBar().getName()).thenReturn("deep");

// note that we're chaining method calls: getBar().getName()
assertEquals("deep", mock.getBar().getName());

AFAIK,链中的第一个方法返回一个模拟,它被设置为在第二个链式方法调用中返回您的值。

Mockito 的作者指出,这应该 _只用于遗留代码_。一个更好的做法是将行为推送到您的 CacheContext 中,并提供它自己完成工作所需的任何信息。您从 CacheContext 中提取的信息量表明您的班级具有 envy 功能

原文由 Lunivore 发布,翻译遵循 CC BY-SA 4.0 许可协议

以防万一您使用的是 Kotlin。 MockK 没有说链接是一种不好的做法,并且很容易让您这样

 val car = mockk<Car>()

every { car.door(DoorType.FRONT_LEFT).windowState() } returns WindowState.UP

car.door(DoorType.FRONT_LEFT) // returns chained mock for Door
car.door(DoorType.FRONT_LEFT).windowState() // returns WindowState.UP

verify { car.door(DoorType.FRONT_LEFT).windowState() }

confirmVerified(car)

原文由 yuranos 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题