Mocking a class that extend some interface used for ServiceLoader implementation

1,039 views
Skip to first unread message

Ratheesh Nair

unread,
Jan 30, 2013, 12:48:30 AM1/30/13
to powe...@googlegroups.com
Hi,

I have a method that use ServiceLoader of Java to check some functionality.

void componentCheck(){

 ServiceLoader<IComponent> loader = ServiceLoader.load(IComponent.class);

        if (null != loader) {

            for (IComponent component : loader) {
                component.check(context);
            }
        }
}

IComponent is the interface have a method check() and there are two classes extend this interface and the full package name of those two classes added in the provider configuration file (META-INF/services/com.example.IComponent )

So I need to write a  unit test to verify that the check() method of the extended class getting called when we test the ServiceLoader implemented method( componentCheck() )

While writing the unit test I mocked the check() method of the extended class using doNothing().when(stateCheck).check(context); 
It is actually calling the orginal method instead of do nothing.

Please let me know whether we need extra configuration/steps to do before mock the method of interface that will assign on runtime when we deal with ServiceLoader 

Thanks






Johan Haleby

unread,
Jan 30, 2013, 2:28:17 AM1/30/13
to powe...@googlegroups.com
Is "stateCheck" an implementation of IComponent? Is the class final? Do you mock the call to ServiceLoader.load?

Regards,
/Johan







--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To unsubscribe from this group and stop receiving emails from it, send an email to powermock+...@googlegroups.com.
To post to this group, send email to powe...@googlegroups.com.
Visit this group at http://groups.google.com/group/powermock?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ratheesh Nair

unread,
Jan 30, 2013, 5:05:58 AM1/30/13
to powe...@googlegroups.com
Yes stateCheck is an object of  the a class that implement IComponet and that class is not final.

I tried to mock ServiceLoader.load but I needed to retrun a mocked ServiceLoader object  of that load() methos that is not yet posible.

I tried the following way but I think we can't mock ServiceLoader class

        ServiceLoader mockServiceLoader = mock(ServiceLoader.class);
        PowerMockito.mockStatic(ServiceLoader.class);
        when(ServiceLoader.load(IComponent.class)).thenReturn(mockServiceLoader);
        IComponent mockComponent = mock(IComponent.class);
        Iterator iterator = mock(Iterator.class);
        when(mockServiceLoader.iterator()).thenReturn(iterator);
        when(iterator.hasNext()).thenReturn(true).thenReturn(false);
        when(iterator.next()).thenReturn(mockComponent);
        doNothing().when(mockComponent).check(context);

Error is 

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class replica.java.util.ServiceLoader$$PowerMock0
Mockito can only mock visible & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:100)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:58)
at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:138)
    

Johan Haleby

unread,
Jan 30, 2013, 6:11:40 AM1/30/13
to powe...@googlegroups.com
Isn't it much simpler to just register the service to the ServiceLoader and then you don't need to mock the "load" method (I'm not overly familiar with ServiceLoader so I'm not sure really how this is done)? In that case you wouldn't even need PowerMock. 

If you really need to mock the ServiceLoader you need to know that it's a java system class that you must treat specially.

Regards,
/Johan
Reply all
Reply to author
Forward
0 new messages