Powermockito不嘲笑URI.toURL()方法中的URL构造函数

问题描述 投票:0回答:1

此单元测试失败。

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);
java junit mockito powermock powermockito
1个回答
0
投票

FAQ

问题:

我无法从java.lang,java.net,java.io或其他系统类中模拟类,为什么?

答案:

这是因为它们是由Java的引导类加载器加载的,并且无法由PowerMock的类加载器操纵字节码。以来PowerMock 1.2.5有一个解决方法,请看一下一个简单的例子,看看它是如何完成的。

请注意,该示例的链接有一个无效的链接,应改为this一个。


user674669写道:

我正在拦截URI类中发生的URL类的构造函数。因此,我正在使用PrepareForTest批注准备URI。

java.net.URI是系统类。如上所述,PowerMockito无法为其操作字节码,因此不会产生任何效果。您将不得不调整其他类的字节码,这意味着您需要在@PrepareForTest批注中定义其他类。


linked article中提到的案例的工作示例:

经过powermock 2.0.7mockito 3.3.3junit 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对象。

© www.soinside.com 2019 - 2024. All rights reserved.