如何使用 PowerMock 模拟被测类以外的其他类的私有方法



我有一个类,我想用一个公共方法进行测试,该方法调用另一个类的私有方法。当我尝试调用同一类的私有方法时,一切正常。当我尝试模拟从被测试类调用的另一个私有方法时,问题就出现了。下面是测试类的代码示例。

@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();
    }
}

以下是所测试类的代码示例

import java.util.Random;
public class CodeWithPrivateMethod {
    CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();
    public void meaningfulPublicApi() {
        if (anotherPrivateMethod.doTheGame("Whatever")) {
            System.out.println("kaboom");
        }
    } 
}

下面是从受测类调用的类的代码示例

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((方法,使其始终返回true?

这里的问题是,尽管您在测试中创建CodeWithAnotherPrivateMethod间谍,但在CodeWithPrivateMethod中创建CodeWithAnotherPrivateMethod的新实例。所以,实际上你没有使用你的模拟。

CodeWithAnotherPrivateMethod anotherPrivateMethod = new CodeWithAnotherPrivateMethod();

为了避免这种情况,您可以在创建新实例时强制返回 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();
}

希望对您有所帮助。

相关内容

  • 没有找到相关文章

最新更新