divz
divz

Reputation: 7957

Mock a jUnit test using powermockito

I am trying to mock the following functionality

public class ServerConnection{
        public ServerConnection(ClientConnection cn) {
            super(cn);
        }

    public void setUrl(String url) {      
                this.url = URLUtil.processURL(url);
                try {
                    URL dst = new URL(this.url);
                    InputStream is = dst.openStream();
                    Scanner scanner = new Scanner(is);

                    StringBuilder sb = new StringBuilder();

                    while(scanner.hasNextLine())
                        sb.append(scanner.nextLine()).append("\n");


                    if (validate(sb.toString())) {
                       --------
                    } else {    }
                    is.close();
                    scanner.close();
                } catch (Exception ex) {

                }        
        }

    private boolean validate(String content) {
            JSONParser parser = new JSONParser();
            Boolean isJsonValid = false;
            JSONObject json = null;
            try {
              --------
              //json validation goes here
            } catch (Exception e) {          
            }
            return isJsonValid;
        }

        public void setId(Integer id) {
        if(id == null)
        this.id = 0;
        else
        this.id = id;
        }
}

PowerMockito Junit code

@RunWith(PowerMockRunner.class)
@PrepareForTest({PathTest.class })
public class URLTest {
 ServerConnection sc ;
 String URL = "http://test.com";

  @Before
     public void setUp() throws Throwable{              
             ClientConnection con =PathTest.getCon();  // Here getCon() is a static method
             sc = new ServerConnection(con);
             sc.setId(1000); 
     }

@Test
    public void testName() throws Throwable {       

        String expectedResponse = "test";
        URL url = PowerMockito.mock(URL.class);
        HttpURLConnection connection = PowerMockito.mock(HttpURLConnection.class);
        InputStream inputStream = PowerMockito.mock(InputStream.class);
        Scanner scanner = PowerMockito.mock(Scanner.class);

        PowerMockito.whenNew(URL.class).withArguments(URL).thenReturn(url);
        PowerMockito.whenNew(Scanner.class).withArguments(inputStream).thenReturn(scanner);
        PowerMockito.when(scanner.useDelimiter("\\A")).thenReturn(scanner);

        PowerMockito.when(url.openConnection()).thenReturn(connection);

        // Response code mocked here
        PowerMockito.when(connection.getResponseCode()).thenReturn(200);

        PowerMockito.when(connection.getInputStream()).thenReturn(inputStream);
        PowerMockito.when(scanner.hasNext()).thenReturn(true);
        PowerMockito.when(scanner.next()).thenReturn(expectedResponse);

        sc.setUrl(URL);
    }
}

While Iam executing this I observed following error message

URLTest
com.objects.URLTest
testName(com.objects.URLTest)
java.lang.ExceptionInInitializerError

    at java.lang.Class.forName0(Native Method)

    at java.lang.Class.forName(Class.java:264)

    at javassist.runtime.Desc.getClassObject(Desc.java:43)

    at javassist.runtime.Desc.getClassType(Desc.java:152)

    at javassist.runtime.Desc.getType(Desc.java:122)

    at javassist.runtime.Desc.getType(Desc.java:78)

    at com.objects.PathTest.getCon(TargetPathTest.java:24)

    at com.objects.URLTest.setUp(URLTest.java:41)

    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.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:133)

    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)

    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)

    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)

    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)

    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)

    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)

    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)

    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)

    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)

    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)

    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)

    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)

    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)

    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)

    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Caused by: java.lang.NullPointerException   

    ... 38 more

Upvotes: 1

Views: 793

Answers (1)

GhostCat
GhostCat

Reputation: 140427

So many things wrong with this code.

The first technical answer is: you seem to not know what you are doing. You have @PrepareForTest({PathTest.class }) which indicates that you intend to mock a static method of that class.

But then you aren't doing what is necessary to mock a static method in that class. Simply follow their documentation step by step. I also think that the URL class is final, so you would have to prepare-annotate that class as well, in order for it be used with whenNew()!

But then: you should avoid mocking URL or URL connection objects. Simply use some sort of dependency injection, and make sure you can pass some mocked instance into your code under test, for example using the @InjectMocks annotation of Mockito. From there, you might also avoid using a static method.

Long story short: your production code is badly written, and your unit test is (honestly) plain horrible. You should seriously step back here, and throw that stuff away. Then re-think your production code to not use new directly, and to not rely on static methods. By doing so, you can get rid of PowerMockito, you go with ordinary Mockito (well, you need to enable mocking of final classes). But rest assured: there is no point in using PowerMock(ito) unless you absolutely have to.

And then: don't "invent" mocking code. Read tutorials, and follow them step by step. You are mocking like everything in your test case, but you should do the exact opposite: you only mock things when there is absolutely no other way to test your code. And you absolutely do not make a method static when that breaks your ability to reasonably unit test your code.

( static has its place, but when it gets in your way, you are doing the wrong thing ! )

Upvotes: 2

Related Questions