用于链接呼叫的模拟或存根

jil*_*len 63 java unit-testing mocking mockito

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());
}
Run Code Online (Sandbox Code Playgroud)

这是测试的方法,

Method targetMethod = ctx.getTargetMethod();
CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);
Run Code Online (Sandbox Code Playgroud)

我必须模拟三个CacheContext,Method和CacheEnable.有什么想法让测试用例更简单吗?

Lun*_*ore 133

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());
Run Code Online (Sandbox Code Playgroud)

AFAIK,链中的第一个方法返回一个mock,它被设置为在第二个链式方法调用上返回你的值.

Mockito的作者指出,这应仅用于遗留代码.否则更好的做法是将行为推送到CacheContext中,并提供完成工作所需的任何信息.您从CacheContext中提取的信息量表明您的类具有令人羡慕的功能.

  • @Magnilex实际上是官方资料。如上所示,源代码。“请注意,在大多数情况下,模拟返回模拟是错误的。” 另外:警告:常规清洁代码很少需要使用此功能!留给旧代码。模拟一个模拟返回一个模拟,返回一个模拟,(...),返回一些有意义的提示,以违反违反Demeter法则或模拟一个值对象(众所周知的反模式)。https://github.com/mockito/mockito/blob/master/src/main/java/org/mockito/Mockito.java(大部分在1393行)。 (3认同)
  • Feture envy 定义已移至此处:https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md (2认同)

yur*_*s87 8

以防万一您正在使用 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)
Run Code Online (Sandbox Code Playgroud)


小智 6

扩展Lunivore 的答案,对于任何注入模拟豆的人,请使用:

@Mock(answer=RETURNS_DEEP_STUBS)
private Foo mockedFoo;
Run Code Online (Sandbox Code Playgroud)