Из FAQ :
Вопрос:
Я не могу макетировать классы из java .lang, java. net, java .io или другие системные классы, почему?
Ответ:
Это потому, что они загружены Java bootstrap classloader и не может быть обработан байт-кодом загрузчиком классов PowerMock . Поскольку в PowerMock 1.2.5 есть обходной путь, ознакомьтесь с этим простым примером, чтобы увидеть, как это делается.
Обратите внимание, что ссылка на пример не работает, она должна быть this one вместо
user674669 wrote:
Я перехватываю конструктор класса URL, который происходит в классе URI.
Вы пытаетесь это сделать. Однако это завершается с ошибкой (и вместо этого создается реальный объект).
user674669 wrote:
Итак, я готовлю URI с использованием аннотации PrepareForTest.
java.net.URI
- системный класс. Как упоминалось выше, PowerMockito
не может манипулировать байт-кодом для него, поэтому он не будет иметь никакого эффекта. Вместо этого вам придется настроить байт-код другого класса, что подразумевает, что вам нужно определить другой класс в аннотации @PrepareForTest
.
Рабочий пример для случая, упомянутого в связанная статья :
Протестировано с powermock 2.0.7
, mockito 3.3.3
, junit 4
public class ClassUnderTest {
public InputStream method(boolean param, URI uri) throws Exception {
String scheme = param ? "https" : "http";
URI replacedUri = new URI(scheme, uri.getAuthority(), uri.getPath(), uri.getQuery(), uri.getFragment());
return replacedUri.toURL().openStream();
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassUnderTest.class)
public class MyTest {
@Test
public void testMethod() throws Exception {
URI uri = new URI("blah://localhost");
FileInputStream fis = new FileInputStream(new File(".", "existing.file"));
URI uriMock = PowerMockito.mock(URI.class);
URL urlMock = PowerMockito.mock(URL.class);
PowerMockito.whenNew(URI.class).withAnyArguments().thenReturn(uriMock);
Mockito.when(uriMock.toURL()).thenReturn(urlMock);
Mockito.when(urlMock.openStream()).thenReturn(fis);
ClassUnderTest testObject = new ClassUnderTest();
InputStream is = testObject.method(false, uri);
Assert.assertEquals(fis, is);
}
}
Это работает, потому что байт-код ClassUnderTest
модифицируется и вместо него создается реальный объект URI
.