mockito - PowerMockito 在定义第二个“when”子句时调用 Mocked Object 上的真实方法
问题描述
当使用不同的参数调用方法时,我试图定义一些不同的模拟行为。不幸的是,我发现第二次尝试在(模拟)类上模拟给定方法时,它运行实际方法,导致异常,因为匹配器不是有效参数。任何人都知道我可以如何防止这种情况?
manager = PowerMockito.mock(Manager.class);
try {
PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
.thenReturn(manager);
} catch (Exception e) {
e.printStackTrace();
}
FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(Matchers.eq(VALID_IK),
Matchers.eq(VALID_CATEGORY_NAME))).thenReturn(validFindAuthorityDescription);
PowerMockito.when(manager.processRequest(Matchers.any(FindAuthorityDescriptionRequest.class)))
.thenThrow(ManagerException.class);
PowerMockito.when(manager.processRequest(Matchers.eq(validFindAuthorityDescription)))
.thenReturn(generateValidAuthorityDescriptionResponse());
解决方案
以下代码是基于您的模拟设置的工作示例(我添加了虚拟类以使其可运行)。
该代码还包含用于验证模拟方法是否返回预期值的断言。此外,真正的方法createFindAuthorityDescriptionRequest
只被调用一次。
注意:这是用 `powermock 2.0.7` 和 `mockito 2.21.0` 测试的。
如果问题仍然存在,我建议检查是否没有从程序中的其他地方额外调用真正的方法(除了问题陈述中引用的代码)。
package com.example.stack;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.powermock.api.mockito.PowerMockito.mock;
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.example.stack.*")
public class StackApplicationTests {
private static final String VALID_IK = "IK";
private static final String VALID_CATEGORY_NAME = "CATEGORY_NAME";
private static final Object VALID_RESPONSE = "RESPONSE";
@Test
public void test() {
Manager manager = mock(Manager.class);
try {
PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
.thenReturn(manager);
} catch (Exception e) {
e.printStackTrace();
}
FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
PowerMockito.when(manager.createFindAuthorityDescriptionRequest(eq(VALID_IK), eq(VALID_CATEGORY_NAME)))
.thenReturn(validFindAuthorityDescription);
PowerMockito.when(manager.processRequest(any(FindAuthorityDescriptionRequest.class)))
.thenThrow(ManagerException.class);
PowerMockito.when(manager.processRequest(eq(validFindAuthorityDescription)))
.thenReturn(VALID_RESPONSE);
// verify that the mock returns expected results
assertEquals(Manager.REAL_RESULT, manager.createFindAuthorityDescriptionRequest("any", "any"));
assertEquals(validFindAuthorityDescription, manager.createFindAuthorityDescriptionRequest("IK", "CATEGORY_NAME"));
assertThrows(ManagerException.class, new ThrowingRunnable(){
@Override
public void run( ) {
manager.processRequest(new FindAuthorityDescriptionRequestImpl());
}
});
assertEquals(VALID_RESPONSE, manager.processRequest(validFindAuthorityDescription));
}
}
interface FindAuthorityDescriptionRequest {}
class FindAuthorityDescriptionRequestImpl implements FindAuthorityDescriptionRequest {}
class ManagerException extends RuntimeException {}
class Manager {
public static FindAuthorityDescriptionRequestImpl REAL_RESULT = new FindAuthorityDescriptionRequestImpl();
public Manager(String s1, String s2) {}
public FindAuthorityDescriptionRequest createFindAuthorityDescriptionRequest(String ik, String category) {
return REAL_RESULT;
}
public Object processRequest(FindAuthorityDescriptionRequest request) {
return null;
}
}