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。有没有什么方法可以让测试用例变得更简单?
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());
毫无疑问,链中的第一个方法返回一个mock,它被设置为在第二个链方法调用时返回您的值。
Mockito的作者注意到,这个应该只用于遗留代码。另一种更好的方法是将行为推入CacheContext,并提供完成该工作所需的任何信息。您从CacheContext中提取的信息量表明您的类具有功能嫉妒。
以防您正在使用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)
扩展Lunivore的答案,对于任何注入模拟bean的人,使用:
@Mock(answer=RETURNS_DEEP_STUBS)
private Foo mockedFoo;
为了使您的测试用例更简单,我的建议是重构您的方法。
每当我发现自己在测试一个方法时遇到困难时,这对我来说就是一种代码气味,我就会问为什么它很难测试。如果代码难以测试,那么它可能也难以使用和维护。
在这种情况下,这是因为你有一个方法链,深入到几个层次。可能传入ctx、cacheEnable和cacheExpire作为参数。
我发现JMockit更容易使用,并完全切换到它。查看使用它的测试用例:
https://github.com/ko5tik/andject/blob/master/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java在这里我mock away活动基类,这是来自Android SKD和完全存根。使用JMockit,你可以模拟最终的、私有的、抽象的或其他任何东西。
在您的测试用例中,它看起来像:public void testFoo(@Mocked final Method targetMethod,
@Mocked final CacheContext context,
@Mocked final CacheExpire ce) {
new Expectations() {
{
// specify expected sequence of infocations here
context.getTargetMethod(); returns(method);
}
};
// call your method
assertSomething(objectUndertest.cacheExpire(context))