Need to partially mock a super super super method used in class under test

1,742 views
Skip to first unread message

mike

unread,
Aug 9, 2013, 8:40:48 AM8/9/13
to powe...@googlegroups.com
Hi,

I am trying to test the following code snippet:

@Override
    public boolean isEnabled() {
        IResource[] resources = getSelectedResources();
        if (resources.length == 0)
            return false;
        for (int i = 0; i < resources.length; i++) {
            IResource resource = resources[i];
            ClearCaseProvider provider = ClearCaseProvider.getClearCaseProvider(resource);
            if (provider == null || provider.isUnknownState(resource) || provider.isIgnored(resource) || !provider.isClearCaseElement(resource))
                return false;
            if (provider.isHijacked(resource))
                return false;
        }
        return true;
    }

The method getSelectedResources is contained in a super super super class ( yes I know Composition should be favoured ....) but this is legacy code.

So I tried to do a partial mock for this like:

package net.sourceforge.eclipseccase.ui.test;

import static org.junit.Assert.*;
import net.sourceforge.eclipseccase.ClearCaseProvider;
import net.sourceforge.eclipseccase.ui.actions.HijackAction;

import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
import org.eclipse.core.resources.IResource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * Tests the HiJackAction class.
 * http://easymock.org/EasyMock3_0_Documentation.html
 * 
 * @author eraonel
 * 
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ HijackAction.class })
public class HiJackActionTest extends EasyMockSupport {

    // mock instance
    private IResource resourceMock;
    private HijackAction partialMockedHijackAction;
    private ClearCaseProvider clearcaseProviderMock;
    private IResource [] resources;

    @Before
    public void setup() throws Exception {
        resourceMock = EasyMock.createMock(IResource.class);
        clearcaseProviderMock = EasyMock.createMock(ClearCaseProvider.class);
    }

    @Test
    public void testIsEnabledWhenFileIsNotHijacked() throws Exception {
        
        partialMockedHijackAction = PowerMock.createPartialMock(
                HijackAction.class, "getSelectedResources");
        resources = new IResource[] { resourceMock };
        PowerMock.expectPrivate(partialMockedHijackAction,
                "getSelectedResources").andReturn(resources);
                
        EasyMock.expect(clearcaseProviderMock.getClearCaseProvider(EasyMock
                .anyObject(IResource.class)));
        
        //Could not use use isA(IResource.class since I got 
        EasyMock.expect(clearcaseProviderMock.isUnknownState(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isIgnored(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isClearCaseElement(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isHijacked(resourceMock)).andReturn(false);

        // switch to replay state ( use interface) for all mocks.
        replayAll();
        // test that isEnabled returns true
        assertTrue(partialMockedHijackAction.isEnabled());
        // verify that specified behaviour has been used all mocks at once
        verifyAll();

    }

}

However when I step the code I can see that:

 IResource[] resources = getSelectedResources();

resources is null.

So it seems that the partialMock of the getSelectedResources is not successful.
Any ideas how I can mock it?

//mike

Johan Haleby

unread,
Aug 19, 2013, 2:33:49 AM8/19/13
to powe...@googlegroups.com
Could it be because you extend from EasyMockSupport? In that case you don't use replayAll() and verifyAll() from PowerMock (which you must statically import). You should not extend from EasyMockSupport when using PowerMock.

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.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

mike

unread,
Aug 21, 2013, 2:42:06 AM8/21/13
to powe...@googlegroups.com
I changed the code to the following:

package net.sourceforge.eclipseccase.ui.test;

import junit.framework.TestCase;
import net.sourceforge.eclipseccase.ClearCaseProvider;
import net.sourceforge.eclipseccase.ui.actions.HijackAction;

import org.easymock.EasyMock;
import org.eclipse.core.resources.IResource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * Tests the HiJackAction class.
 * http://easymock.org/EasyMock3_0_Documentation.html
 * 
 * @author eraonel
 * 
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ HijackAction.class ,ClearCaseProvider.class})
public class HiJackActionTest extends TestCase{
    
    //TODO: This class is not ready yet. Check forum.
    //https://groups.google.com/forum/#!forum/powermock
    
    // mock instance
    private IResource resourceMock;
    private HijackAction partialMockedHijackAction;
    private ClearCaseProvider clearcaseProviderMock;
    private IResource [] resources;

    @Before
    public void setup() throws Exception {
        resourceMock =
 EasyMock.createMock(IResource.class);
        clearcaseProviderMock = PowerMock.createMock(ClearCaseProvider.class);
        
    }

    @Test
    
public void testIsEnabledWhenFileIsNotHijacked() throws Exception {
        
        partialMockedHijackAction = PowerMock.createPartialMock(
                HijackAction.class, "getSelectedResources");
        resources = new IResource[] { resourceMock };
        PowerMock.expectPrivate(partialMockedHijackAction,
                "getSelectedResources"
).andReturn(resources);
        
        PowerMock.mockStatic(ClearCaseProvider.class);
        EasyMock.expect(ClearCaseProvider.getClearCaseProvider(EasyMock
                .anyObject(IResource.class))).andReturn(clearcaseProviderMock);
        
        
//Could not use use isA(IResource.class since I got 
        EasyMock.expect(clearcaseProviderMock.isUnknownState(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isIgnored(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isClearCaseElement(resourceMock)).andReturn(false);
                
        EasyMock.expect(clearcaseProviderMock.isHijacked(resourceMock)).andReturn(false);

        // switch to replay state ( use interface) for all mocks.
        PowerMock.replayAll();
        // test that isEnabled returns is false.
        assertFalse(partialMockedHijackAction.isEnabled());
        
// verify that specified behaviour has been used all mocks at once
        PowerMock.verifyAll();

    }

}
 
But I get the error message:

java.lang.IllegalStateException: no last call on a mock available
    at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
    at org.easymock.EasyMock.expect(EasyMock.java:499)
    at net.sourceforge.eclipseccase.ui.test.HiJackActionTest.testIsEnabledWhenFileIsNotHijacked(HiJackActionTest.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    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:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    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:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Message points to the following line in my test:


  EasyMock.expect(ClearCaseProvider.getClearCaseProvider(EasyMock
                .anyObject(IResource.class))).andReturn(clearcaseProviderMock);


Any ideas of the cause and how to fix it?

br,

//mike

Johan Haleby

unread,
Aug 22, 2013, 1:44:25 AM8/22/13
to powe...@googlegroups.com
Hmm it's a bit hard when I don't know what HijackAction and ClearCaseProvider looks like. The best thing would be if you could attach a small maven project demonstrating the issue.

/Johan
Reply all
Reply to author
Forward
0 new messages