Я использую PowerMock для насмешки java.net.Inet4Address (помимо прочего), чтобы вернуть определенный IP-адрес (getHostAddress()
), а также проверить, является ли он закольцованным (isLoopbackAddress()
). Я обнаружил, что если я выполняю фактическую заглушку (PowerMock.doReturn(...).when(mock).methodToStub()
) где-либо, кроме как внутри тестового класса или непосредственно внутреннего класса, я получаю исключение UnfinishedStubbingException.
Проблема наиболее очевидна, если я пытаюсь выполнить две заглушки,Первый проходит без исключения, но второй выдает исключение, потому что думает, что первый не был закончен. Если я выполняю только одну заглушку, то я вижу разные ошибки в зависимости от того, что я делаю после этого, так что это определенно первая заглушка, которая вызывает проблему.
Ниже приведен код, демонстрирующий проблему.
TestClass.java
/* package, imports... */
@RunWith(PowerMockRunner.class)
@PrepareForTest({Inet4Address.class})
public class TestClass {
@Test
public void test() {
Inet4Address mocked = PowerMockito.mock(Inet4Address.class);
// Option 1: Do it from within this class - WORKS
doStubbing(mocked);
// Option 2: Do it from an inner class - WORKS
Inner.doStubbing(mocked);
// Option 3: Do it from an inner class of the inner class - FAILS
Inner.Deeper.doStubbing(mocked);
// Option 4: Do it from an entirely different class - FAILS
OtherClass.doStubbing(mocked);
}
private void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
public static class Inner {
static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
public static class Deeper {
static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
}
}
}
OtherClass.java
/* package, imports... */
public class OtherClass {
public static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
}
Я поместил создание макета в начале, общий для всех сценариев. Не имеет значения, создается ли макет из того же класса, где выполняется заглушка. Я также сделал методы статичными для удобства чтения;Поведение остается прежним, если сначала создаются экземпляры классов.
Я знаю, что есть обходные пути, чтобы я мог заставить свой тест работать (выполните макетирование прямо в классе теста, смоделируйте интерфейс InetAddress вместо реализации IPv4и т. д.), но я хотел бы знать, почему PowerMock ведет себя так. Я мог бы почти понять это, если бы он работал только внутри тестового класса, но почему он работает и во внутреннем классе?