该单元测试失败。
package com.abc;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.net.URI;
import java.net.URL;
import static org.junit.Assert.assertEquals;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PrepareForTest({URI.class})
public class ITest2 {
@Test
public void test5() throws Exception {
URI uri = new URI("http://www.google.com");
final URL resourceUrl = ClassLoader.getSystemClassLoader().getResource("static/abc.png"); //EXISTS
PowerMockito.whenNew(URL.class).withArguments(
"http://www.google.com")
.thenReturn(resourceUrl);
URL url = uri.toURL(); // <--- At this point, url should be == resourceUrl
assertEquals(resourceUrl, url); // <--- url is http://www.google.com and not ".../static/abc.png"
}
}
该单元测试失败。
java.lang.AssertionError:
Expected :file:/Users/hidden/target/classes/static/abc.png
Actual :http://www.google.com
<Click to see difference>
您知道为什么url!= resourceUrl吗?我想念什么?
这是URI.toURL()的代码:
public URL toURL()
throws MalformedURLException {
if (!isAbsolute())
throw new IllegalArgumentException("URI is not absolute");
return new URL(toString());
}
使用Mockito 2.15和Powermock 2.0.7。
谢谢。
更新:
添加这些命令也无济于事。只是入侵而已。
PowerMockito.whenNew(URL.class).withArguments(
eq("http://www.google.com"))
.thenReturn(resourceUrl);
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(resourceUrl);
PowerMockito.whenNew(URL.class).withArguments(any()).thenReturn(resourceUrl);
PowerMockito.whenNew("java.net.URL").withArguments(any()).thenReturn(resourceUrl);
PowerMockito.whenNew(URL.class).withParameterTypes(String.class)
.withArguments("http://www.google.com")
.thenReturn(resourceUrl);
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(resourceUrl);
PowerMockito.whenNew(URL.class).withNoArguments().thenReturn(resourceUrl);
答案 0 :(得分:0)
来自FAQ:
问题:
我不能从java.lang,java.net,java.io或其他系统类中模拟类,为什么?
答案:
这是因为它们是由Java的引导类加载器和加载的 无法由PowerMock的类加载器操纵字节码。以来 PowerMock 1.2.5有一个解决方法,请看一下 一个简单的例子,看看它是如何完成的。
请注意,该示例的链接有一个无效的链接,应改为this一个。
user674669写道:
我正在拦截发生在URI类中的URL类的构造函数。
您正在尝试这样做。但是,此操作失败失败(并且创建了真实对象)。
user674669写道:
因此,我正在使用PrepareForTest注释准备URI。
java.net.URI
是系统类。如上所述,PowerMockito
不能为其操作字节码,因此不会产生任何效果。您将不得不调整其他类的字节码,这意味着您需要在@PrepareForTest
批注中定义其他类。
linked article中提到的案例的工作示例:
经过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
对象。