使用PowerMock模拟了私有方法,但是仍然调用了底层方法

我正在尝试模拟一个进行JNDI调用的私有方法。从单元测试中调用该方法时,它将引发异常^。我想模拟该方法用于测试目的。我使用了另一个问题answer中的示例代码,并且在测试通过时,似乎仍在调用底层方法。我System.err.println()doTheGamble()方法中插入,然后将其打印到控制台。

有趣的是,如果我将第一个注释掉assertThat,则测试通过。?:(

那么,我如何模拟出一个私有方法,使其不被调用?

import static org.hamcrest.core.Is.is;

import static org.junit.Assert.assertThat;

import static org.mockito.Matchers.anyInt;

import static org.mockito.Matchers.anyString;

import static org.powermock.api.mockito.PowerMockito.when;

import static org.powermock.api.support.membermodification.MemberMatcher.method;

import java.util.Random;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)

@PrepareForTest(CodeWithPrivateMethod.class)

public class PowerMock_Test {

static boolean gambleCalled = false;

@Test(expected = RuntimeException.class)

public void when_gambling_is_true_then_always_explode() throws Exception {

CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());

when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class))

.withArguments(anyString(), anyInt())

.thenReturn(true);

/* 1 */ assertThat( PowerMock_Test.gambleCalled, is(false) );

spy.meaningfulPublicApi();

/* 2 */ assertThat( PowerMock_Test.gambleCalled, is(false) );

}

}

class CodeWithPrivateMethod {

public void meaningfulPublicApi() {

if (doTheGamble("Whatever", 1 << 3)) {

throw new RuntimeException("boom");

}

}

private boolean doTheGamble(String whatever, int binary) {

Random random = new Random(System.nanoTime());

boolean gamble = random.nextBoolean();

System.err.println( "\n>>> GAMBLE CALLED <<<\n" );

PowerMock_Test.gambleCalled = true;

return gamble;

}

}

^可以理解,由于我的工作空间不支持JNDI,因此只有生产环境可以

我正在使用所有库的最新版本,包括JUnit 4.10,Mockito 1.8.5,Hamcrest 1.1,Javassist3.15.0和PowerMock 1.4.10。

回答:

从PowerMock私有方法示例中:

@RunWith(PowerMockRunner.class)

// We prepare PartialMockClass for test because it's final or we need to mock private or static methods

@PrepareForTest(PartialMockClass.class)

public class YourTestCase {

@Test

public void privatePartialMockingWithPowerMock() {

PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());

// use PowerMockito to set up your expectation

PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");

// execute your test

classUnderTest.execute();

// Use PowerMockito.verify() to verify result

PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");

}

因此,将其应用于您的代码,我认为它可能变为:

@RunWith(PowerMockRunner.class)

@PrepareForTest(CodeWithPrivateMethod.class)

public class PowerMock_Test {

@Test(expected = RuntimeException.class)

public void when_gambling_is_true_then_always_explode() throws Exception {

CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());

PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt());

/* 1 */ PowerMockito.verifyPrivate(spy, times(0)).invoke("doTheGamble", anyString(), anyInt());

spy.meaningfulPublicApi();

/* 2 */ PowerMockito.verifyPrivate(spy, times(2)).invoke("doTheGamble", anyString(), anyInt());

}

}

我只是在这里的编辑器中进行了编码。实际没有运行任何测试,并且在编写此代码时没有损害任何错误。

以上是 使用PowerMock模拟了私有方法,但是仍然调用了底层方法 的全部内容, 来源链接: utcz.com/qa/423493.html

回到顶部