基于模拟反射的调用

2022-09-03 18:04:32

我试图嘲笑一些基于反射的方法。下面你可以看到细节,

测试中的类

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。我知道我在嘲笑概念方面做错了什么,但我不明白它是什么。您能不能对此进行一些说明,并建议我如何测试此方法?

谢谢。


答案 1

您需要一个方法对象和一个类对象。根据您的评论,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);

显然,不会再返回“someMethod”,并且会返回此测试类的名称(在示例中),但是尽管您无法选择它们返回的内容,但它们返回的内容仍然是确定性的,因此您应该能够验证所需的任何内容。(当然,如果您需要监视或验证是否对 Method 对象本身进行了调用,您仍然会陷入困境。getName()getDeclaringClass().getName()


答案 2

是的,问题是将返回空值。因此,每次运行此命令时,然后在结果上调用某些内容(getDeclaringClass()或getName()),您将获得NPE。在设置模拟时,您可能希望使用默认答案。类似的东西mockContext.getMethod()RETURNS_DEEP_STUBS

@Mock( answer = RETURNS_DEEP_STUBS ) private InvocationContext mockContext; 

应该做这个把戏。


推荐