模拟基于反射的呼叫
问题内容:
我正在尝试模拟一些基于反射的方法。您可以在下面看到详细信息,
被测课程
public class TracerLog {
@AroundInvoke
public Object logCall(InvocationContext context) throws Exception {
Logger logger = new Logger();
String message = "INFO: Invoking method - "
+ context.getMethod().getName() + "() of Class - "
+ context.getMethod().getDeclaringClass();
logger.write(message);
return context.proceed();
}
}
测试
public class TracerLogTest {
@Mock
InvocationContext mockContext;
@Mock
Logger mockLogger;
@InjectMocks
private TracerLog cut = new TracerLog();
@BeforeMethod
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void logCallTest() throws Exception {
when(mockContext.proceed()).thenReturn(true);
when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass");
cut.logCall(mockContext);
verify(mockContext).proceed();
}
}
要么
@Test
public void logCallTest() throws Exception {
when(mockContext.proceed()).thenReturn(true);
when(mockContext.getMethod().getName()).thenReturn("someMethod");
when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass");
cut.logCall(mockContext);
verify(mockLogger).write(anyString());
verify(mockContext).proceed();
}
但是,测试失败,并显示NullPointerException。我知道我在嘲笑概念上做错了什么,但是我不明白这是什么。您能否对此加以说明,并建议我如何测试此方法?
谢谢。
问题答案:
您需要一个Method对象和一个Class对象。根据您的评论,Mockito无法模拟方法,因此您需要一个真正的方法。我还没有测试过,但是我相信这会起作用。代替:
when(mockContext.getMethod().getName()).thenReturn("someMethod");
when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass");
你需要:
// any method will do, but here is an example of how to get one.
Method testMethod = this.getClass().getMethod("logCallTest");
when(mockContext.getMethod()).thenReturn(testMethod);
显然,getName()
将不再返回“
someMethod”,并且getDeclaringClass().getName()
将返回此测试类的名称(在示例中),但是尽管您无法选择它们返回的内容,但是它们返回的内容仍是确定性的,因此您应该能够验证任何内容你需要。(当然,如果您需要监视或验证是否已对Method对象本身进行了调用,则仍然会遇到问题。)