6

Without going into the details of the merit of doing this way, just need help figuring out why the following test codes do not work! This has been more of a learning exercise at this point..

Just trying to use PowerMockito to create a mock for the URL class, and define some behaviors for it. Here's the code:

package com.icidigital.services

import com.icidigital.services.impl.WeatherServiceImpl
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner


/**
 * Created by apil.tamang on 7/27/15.
 * I could not get the setup to finish! Failed!
 */
@PrepareForTest(URL.class)
@RunWith(PowerMockRunner.class)
class WeatherServiceImplTest {


    URL mockURL;
    URLConnection mockConn;

    @Before
    public void setUp(){

        byte[] data = "123,456".getBytes();

        InputStream input = new ByteArrayInputStream(data);

        //define and set behavior for mockConn
        mockConn=PowerMockito.mock(HttpURLConnection.class);
        //Mockito.doCallRealMethod().when(mockConn).getResponseCode();
        //Mockito.when(mockConn.getResponseCode()).thenCallRealMethod().thenReturn(200);
        //Mockito.when(mockConn.getInputStream()).thenReturn(input);

        //define and set behavior for mockURLObj
        mockURL=PowerMockito.mock(URL.class);
        PowerMockito.when(mockURL.openConnection()).thenReturn(mockConn);


    }

    @Test
    public void testSetup(){

        WeatherServiceImpl testObj=new WeatherServiceImpl(mockURL);
        String response=testObj.run("foobar");
        PowerMockito.verifyNew(mockURL);





    }

}

The following exception stack is thrown. In particular, linke 39 of this test, which is where I have: PowerMockito.when(mockURL.openConnection()).thenReturn(mockConn); throws the error. Mind you that URL is a final class, and that's I'm using Powermockito.

java.lang.AbstractMethodError
    at java.net.URL.openConnection(URL.java:971)
    at java_net_URL$openConnection.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at com.icidigital.services.WeatherServiceImplTest.setUp(WeatherServiceImplTest.groovy:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:129)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:93)
apil.tamang
  • 2,545
  • 7
  • 29
  • 40
  • I'm having the same AbstractMethodError with PowerMockito and URL.openConnection(). Did you ever find an answer? I saw a similar question about a different method call at [http://stackoverflow.com/questions/30402750/abstractmethoderror-when-calling-powermockito-mockstatic] – user823981 Sep 17 '15 at 23:56
  • I did.. It is mentioned below. Just make sure you're including the classes you are trying to mock in the @PrepareForTest annotation. – apil.tamang Sep 20 '15 at 16:20
  • Ah, thanks! I had forgotten to put the class under test in @PrepareForTest. – user823981 Sep 21 '15 at 18:35

3 Answers3

5

Well this isn't exactly a solution, and I've simply graduated a different error now, but at least the annoying 'AbstractMethodError' is now gone.

What I did was to add the following classes for the prepareClassForTest annotation:

....
@PrepareForTest({URL.class, URLConnection.class, WeatherServiceImplTest.class} )
...

Was mildly suspicious, but the following post kind of affirmed that doubt: powermock puzzler

Anyways, wish me luck guys. Second day of mocking my way around, and I'm all mucked up and ready to drop the ball...

apil.tamang
  • 2,545
  • 7
  • 29
  • 40
2

I am not really sure, but try to use Mockito for mocking the method call. It seems I have already had such problem, and I think there is some bug from PowerMockito side.

As I remember if you will use

Mockito.when(mockURL.openConnection()).thenReturn(mockConn);

instead of

PowerMockito.when(mockURL.openConnection()).thenReturn(mockConn);

it will work normally.

Or If it is wrong try to use alternative way such as

Mockito/PowerMockito.doReturn(mockConn).when(mockUrl).openConnection();

And if some of these will work, it seems the reason is unhandled situation by PowerMockito dev team. And power mockito invoke real method as well as or instead of mocked method.

Eugene Stepanenkov
  • 896
  • 16
  • 34
  • I don't think I could use Mockito.when(... ) since URL is a final class. But I'll give the second one a shot!! – apil.tamang Jul 29 '15 at 13:41
  • actually try the first thing also, because of powermockito mocks the objects with understandable for mockito mock object. It is integrated with mockito. – Eugene Stepanenkov Jul 29 '15 at 13:44
  • No luck trying that. I'm informed that Mockito cannot mock/spy a final class. – apil.tamang Jul 29 '15 at 13:53
  • @apil.tamang if you have got answer for above question can you help me here. [link](http://stackoverflow.com/questions/39031175/testing-powermock-simulate-http-server-time-out-for-client-call?noredirect=1#comment65533595_39031175) – RK3 Aug 23 '16 at 09:24
2

URL is final class. To mock final class we can use PowerMockito with Junit. To mock final class we need to annotate Test class with @RunWith(PowerMockRunner.class) and @PrepareForTest({ URL.class })


@RunWith(PowerMockRunner.class) 
@PrepareForTest({ URL.class })
public class Test {
    @Test
    public void test() throws Exception {
        URL url = PowerMockito.mock(URL.class);
        HttpURLConnection huc = Mockito.mock(HttpURLConnection.class);
        PowerMockito.when(url.openConnection()).thenReturn(huc);
        assertTrue(url.openConnection() instanceof HttpURLConnection);
    }
}

But in the line PowerMockito.when(url.openConnection()).thenReturn(huc); following error is thrown:

java.lang.AbstractMethodError
    at java.net.URL.openConnection(URL.java:971)
    at java_net_URL$openConnection.call(Unknown Source) 

In order to get rid of this error we can modify our Test class as shown below:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ URL.class })
public class Test {
    @Test
    public void test() throws Exception {

        public class UrlWrapper {

            URL url;

            public UrlWrapper(String spec) throws MalformedURLException {
                url = new URL(spec);
            }

            public URLConnection openConnection() throws IOException {
                return url.openConnection();
            }
        }

        UrlWrapper url = Mockito.mock(UrlWrapper.class);
        HttpURLConnection huc = Mockito.mock(HttpURLConnection.class);
        PowerMockito.when(url.openConnection()).thenReturn(huc);
        assertTrue(url.openConnection() instanceof HttpURLConnection);
    }
}

Visit: https://programmingproblemsandsolutions.blogspot.com/2019/04/abstractmethoderror-is-thrown-on.html