java.lang.NullPointerException on Url mock tests



我对 Url 连接的测试工作正常。然后 1 个月后,我在应用程序中运行了所有测试,并且 URL 连接测试失败,我不知道为什么,因为我没有更改这个类。拜托,有人可以看看这个测试吗?

测试现在抛出java.lang.NullPointerException

测试的最初想法来自: https://programmingproblemsandsolutions.blogspot.com/2019/04/abstractmethoderror-is-thrown-on.html

测试:

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import static org.junit.jupiter.api.Assertions.assertTrue;
@RunWith(PowerMockRunner.class)
@PrepareForTest({URL.class})
class JsonOutputFromURLImplTest
{
    @Test
    void currencyValuesNBP() throws IOException
    {
        class UrlWrapper
        {
            private URL url;
            public UrlWrapper(String spec) throws MalformedURLException
            {
                url = new URL(spec);
            }
            private URLConnection openConnection() throws IOException
            {
                return url.openConnection();
            }
        }
        UrlWrapper url = PowerMockito.mock(UrlWrapper.class);
        HttpURLConnection httpURLConnection = Mockito.mock(HttpURLConnection.class);
        PowerMockito.when(url.openConnection()).thenReturn(httpURLConnection);
        assertTrue(url.openConnection() instanceof HttpURLConnection);
    }
}

测试类:

@Service
@NoArgsConstructor
public class JsonOutputFromURLImpl implements JsonOutputFromURL
{
    @Override
    public String currencyValuesNBP(String APIUrl) throws ConnectionWithApiEX
    {
        String jsonOutput = null;
        try {
            URL url = new URL(APIUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setRequestProperty("Content-Type", "application/json");
            InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            jsonOutput = bufferedReader.readLine();
            httpURLConnection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(jsonOutput != null)
            return jsonOutput;
        throw new ConnectionWithApiEX(APIUrl);
    }
}
java.lang.NullPointerException
    at com.bartosz.kolej.stock.service.impl.JsonOutputFromURLImplTest$1UrlWrapper.openConnection(JsonOutputFromURLImplTest.java:36)
    at com.bartosz.kolej.stock.service.impl.JsonOutputFromURLImplTest$1UrlWrapper.access$000(JsonOutputFromURLImplTest.java:25)
    at com.bartosz.kolej.stock.service.impl.JsonOutputFromURLImplTest.currencyValuesNBP(JsonOutputFromURLImplTest.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
    at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

简短的回答:将您的UrlWrapper.openConnection标记为公开,您就可以开始了。

其次:您没有在服务类中测试任何方法,它的代码无关紧要。

第三:PowerMock可以模拟私有方法,它不适合您的原因非常复杂。

  • 您使用 Junit 5 注释。使用 JUnit4 和 JUnit5 注释时,同一测试的行为会有所不同

考虑以下类

public static class MyClass {
    public String A() {
        System.out.println("A called");
        return "A";
    }
    private String B() {
        System.out.println("B called");
        return "B";
    }
}

使用 Junit4 注释:

@org.junit.Test
public void testMockPrivateMethod() throws Exception {
    MyClass myClass = PowerMockito.mock(MyClass.class);
    PowerMockito.when(myClass.B()).thenReturn("mockB");
    //PowerMockito.when(myClass, "B").thenReturn("mockB");
    System.out.println(myClass.B());
}
Output:
mockB

使用 Junit5 注释:

@org.junit.jupiter.api.Test
public void testMockPrivateMethod() throws Exception {
    MyClass myClass = PowerMockito.mock(MyClass.class);
    PowerMockito.when(myClass.B()).thenReturn("mockB");
    System.out.println(myClass.B());
}
Output:
B called
org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

这是因为您需要字节码检测来模拟私有方法。不幸的是,Junit5引擎不使用PowerMockRunner(它有自己的扩展机制(。请注意,您可以将 Junit4 注释与 Junit5 一起使用,但需要导入复古运行器。

如您所见,正在调用真正的方法。遗憾的是,由于您的方法会引发 NPE,因此您看不到异常。

最新更新