java.lang.NullPointerException при фиктивных тестах Url - PullRequest
0 голосов
/ 04 июня 2019

Мой тест для подключения к URL работал правильно.Затем, через 1 месяц, я запустил все тесты в приложении и провалил тест на URL-соединение, я не знаю почему, так как я не изменил этот класс.Пожалуйста, может кто-нибудь взглянуть на этот тест?

Тест теперь выдает java.lang.NullPointerException

Первоначальная идея теста пришла от: https://programmingproblemsandsolutions.blogspot.com/2019/04/abstractmethoderror-is-thrown-on.html

test:

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)

1 Ответ

1 голос
/ 05 июня 2019

Краткий ответ: отметьте свой 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.

...