如何使用 PowerMock 模拟被测 Class 以外的另一个 Class 的私有方法?
How to mock private method of another Class other than the Class under test using PowerMock?
我有一个 class,我想用调用另一个 class 的私有方法的 public 方法对其进行测试。当我尝试调用相同 class 的私有方法时,一切正常。当我尝试模拟另一个从被测 class 调用的私有方法时出现问题。以下是测试的代码示例 class.
@RunWith(PowerMockRunner.class)
@PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
@Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
/*when(codeWithAnotherPrivateMethod, method(CodeWithAnotherPrivateMethod.class, "doTheGame", String.class))
.withArguments(anyString())
.thenReturn(true);*/
PowerMockito.when(codeWithAnotherPrivateMethod, "doTheGame", anyString()).thenReturn(true);
//PowerMockito.doReturn(true).when(codeWithAnotherPrivateMethod, "doTheGamble", anyString(),anyInt());
spy.meaningfulPublicApi();
}
}
以下是测试中 class 的代码示例
import java.util.Random;
public class CodeWithPrivateMethod {
CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();
public void meaningfulPublicApi() {
if (anotherPrivateMethod.doTheGame("Whatever")) {
System.out.println("kaboom");
}
}
}
下面是 class 的代码示例,它从被测 class 中调用
import java.util.Random;
public class CodeWithAnotherPrivateMethod {
public boolean doTheGame(String string) {
return doTheGamble("Whatever", 1 << 3);
}
private boolean doTheGamble(String whatever, int binary) {
Random random = new Random(System.nanoTime());
boolean gamble = random.nextBoolean();
return gamble;
}
}
所以我的问题是如何成功地模拟 CodeWithAnotherPrivateMethod Class 的 doTheGamble() 方法以使其始终 return 为真?
这里的问题是,虽然您在测试中创建了 CodeWithAnotherPrivateMethod
的间谍,但在 CodeWithPrivateMethod
中创建了 CodeWithAnotherPrivateMethod
的新实例。所以,实际上你没有使用你的模拟。
CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();
为避免这种情况,您可以在创建新实例时强制 return 您的 CodeWithAnotherPrivateMethod 模拟。您可以使用 PowerMockito whenNew()
功能来执行此操作。
示例:
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
最后,你的测试应该是这样的:
@Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// Spy CodeWithAnotherPrivateMethod and force return true when doTheGamble is called
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.doReturn(true).when(codeWithAnotherPrivateMethod, "doTheGamble", Mockito.anyString(), Mockito.anyInt());
// Return your mock when a new instance of CodeWithAnotherPrivateMethod is created.
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());
spy.meaningfulPublicApi();
}
希望对您有所帮助。
我有一个 class,我想用调用另一个 class 的私有方法的 public 方法对其进行测试。当我尝试调用相同 class 的私有方法时,一切正常。当我尝试模拟另一个从被测 class 调用的私有方法时出现问题。以下是测试的代码示例 class.
@RunWith(PowerMockRunner.class)
@PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
@Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
/*when(codeWithAnotherPrivateMethod, method(CodeWithAnotherPrivateMethod.class, "doTheGame", String.class))
.withArguments(anyString())
.thenReturn(true);*/
PowerMockito.when(codeWithAnotherPrivateMethod, "doTheGame", anyString()).thenReturn(true);
//PowerMockito.doReturn(true).when(codeWithAnotherPrivateMethod, "doTheGamble", anyString(),anyInt());
spy.meaningfulPublicApi();
}
}
以下是测试中 class 的代码示例
import java.util.Random;
public class CodeWithPrivateMethod {
CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();
public void meaningfulPublicApi() {
if (anotherPrivateMethod.doTheGame("Whatever")) {
System.out.println("kaboom");
}
}
}
下面是 class 的代码示例,它从被测 class 中调用
import java.util.Random;
public class CodeWithAnotherPrivateMethod {
public boolean doTheGame(String string) {
return doTheGamble("Whatever", 1 << 3);
}
private boolean doTheGamble(String whatever, int binary) {
Random random = new Random(System.nanoTime());
boolean gamble = random.nextBoolean();
return gamble;
}
}
所以我的问题是如何成功地模拟 CodeWithAnotherPrivateMethod Class 的 doTheGamble() 方法以使其始终 return 为真?
这里的问题是,虽然您在测试中创建了 CodeWithAnotherPrivateMethod
的间谍,但在 CodeWithPrivateMethod
中创建了 CodeWithAnotherPrivateMethod
的新实例。所以,实际上你没有使用你的模拟。
CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();
为避免这种情况,您可以在创建新实例时强制 return 您的 CodeWithAnotherPrivateMethod 模拟。您可以使用 PowerMockito whenNew()
功能来执行此操作。
示例:
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
最后,你的测试应该是这样的:
@Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// Spy CodeWithAnotherPrivateMethod and force return true when doTheGamble is called
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.doReturn(true).when(codeWithAnotherPrivateMethod, "doTheGamble", Mockito.anyString(), Mockito.anyInt());
// Return your mock when a new instance of CodeWithAnotherPrivateMethod is created.
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());
spy.meaningfulPublicApi();
}
希望对您有所帮助。