0

I am using Powermock 1.4.9 with Easymock extension.

Following is the method that i want to test

Public class SomeClass {
    public String methodToTest(String id) throws Exception {
        try {
            ClassA ojbectA = MyFactory.staticMethod();
            String str = helperMethod(id);
            ojbectA.methodA(str);
            return objectA.methodB(str);
        }
        catch (Exception e) {
            throw e;
        }
    }
}

Following is the test class and the test which i have written to test the above method. I use both PowerMock and EasyMock as i have Static and Private method call.

import org.easymock.EasyMock;
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;

import static org.easymock.EasyMock.isA;
import static org.powermock.api.easymock.PowerMock.mockStatic;

@RunWith(PowerMockRunner.class)
@PrepareForTest{{SomeClass.class,MyFactory.class, ClassA.class}}
public class TestClass {
@Test
public void testMethod1() {
    try {
        ClassA mockA = PowerMock.createMock(ClassA.class);
        mockStatic(MyFactory.class);
        SomeClass someObj = PowerMock.createPartialMock(SomeClass.class,"helperMethod");

        String mockLog = "This is sample";
        String mockId = "mockId";
        String woMockId = "WO_mockId";

        //Mock all static methods
        EasyMock.expect(MyFactory.staticMethod()).andReturn(mockA);

        //Partial mocking
        PowerMock.expectPrivate(someObj,"helperMethod",mockId).andReturn(woMockId);

        //Mock methodA(String) method
        mockA.methodA(EasyMock.isA(String.class));
        PowerMock.expectLastCall().times(0, 1);

        //When methodB(String) is called, intercept it and return a standard value.
        EasyMock.expect(mockA.methodB(isA(String.class))).andReturn(mockLog);

        EasyMock.replay(mockA);
        EasyMock.replay(someObj);
        PowerMock.replay(MyFactory.class);

        String obtainedResult = someObj.getWorkorderLogByWoId(mockId);

        assertEquals(obtainedResult,mockLog);


        EasyMock.verify(mockA);
        EasyMock.verify(someObj);
        PowerMock.verify(MyFactory.class);
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}
}

This runs fine without any exception on both Intellij IDEA and Eclipse. But, when i run this test at the command line using ANT, i get the following exception.

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 com.xyz.ems.server.services.workorder.TestClass.testMethod1(TestClass.java:<some_line_number>)
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 junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:518)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1052)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:906)

There was a request for original code without replacing strings. So following is the code.

import com.xyz.ems.common.UnitTestCase;
import com.xyz.ems.server.services.logmessage.LogMessageManager;
import com.xyz.ems.server.services.workorder.database.WorkOrderManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.createPartialMock;
import static org.powermock.api.easymock.PowerMock.expectLastCall;
import static org.powermock.api.easymock.PowerMock.expectPrivate;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.api.easymock.PowerMock.replay;
import static org.powermock.api.easymock.PowerMock.verify;

@RunWith(PowerMockRunner.class)
@PrepareForTest({WorkOrderManager.class,WorkOrderFactory.class,     LogMessageManager.class})
public class WorkOrderManagerPM_JTest extends UnitTestCase {


public WorkOrderManagerPM_JTest(String name) {
    super(name);
}

@Before
public void firstMethod() {
    assertTrue(true);
}

@After
public void lastMethod() {
    assertTrue(true);
}

@Test
public void testGetWoLogByObjectId() {
    try {
        LogMessageManager logMsgMgrMock = createMock(LogMessageManager.class);
        mockStatic(WorkOrderFactory.class);
        WorkOrderManager wMgr = createPartialMock(WorkOrderManager.class,"buildWorkOrderIdString");

        String mockLog = "This is sample";
        String mockId = "mockId";
        String woMockId = "WO_mockId";

        //Mock all static methods
        expect(WorkOrderFactory.getLogMessageManager()).andReturn(logMsgMgrMock);

        //Partial mocking
        expectPrivate(wMgr,"buildWorkOrderIdString",mockId).andReturn(woMockId);

        //Mock openLogMessageDoc() method
        logMsgMgrMock.openLogMessageDoc(isA(String.class));
        expectLastCall().times(0, 1);

        //When getAllLogMessageAsString() is called, intercept it and return a standard value.
        expect(logMsgMgrMock.getAllLogMessagesAsString(isA(String.class))).andReturn(mockLog);

        replay(logMsgMgrMock);
        replay(wMgr);
        replay(WorkOrderFactory.class);

        String obtainedResult = wMgr.getWorkorderLogByWoId(mockId);

        assertEquals("getWorkorderLogByWoId() general case passed",obtainedResult,mockLog);


        verify(logMsgMgrMock);
        verify(wMgr);
        verify(WorkOrderFactory.class);
    }
    catch (Exception e) {
        e.printStackTrace();
        fail("Failed to test getWorkorderLogById()");
    }
}

And the original method under test ...

public class WorkOrderManager {
public String getWorkorderLogByWoId(String woId) throws WorkOrderServiceEMSException {
    try {
        LogMessageManager logMsgMgr = WorkOrderFactory.getLogMessageManager();
        String workOrderLogId = buildWorkOrderIdString(woId);
        logMsgMgr.openLogMessageDoc(workOrderLogId);
        return logMsgMgr.getAllLogMessagesAsString(workOrderLogId);
    }
    catch (Exception e) {
        String msg = "Failed to get Work Order Log for workorder Id : " + woId;
        throw new WorkOrderServiceEMSException(msg, WorkOrderServiceEMSError.WO_GET_WOLOG_BY_OBJECTID.newInstanceWithFormatArgs(woId), e);
    }
}
}
maverick
  • 549
  • 2
  • 10
  • 18

1 Answers1

0

Try this....

package com.chumma.pdf.main;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest( { SomeClass.class, MyFactory.class, ClassA.class })
public class SomeClassTest {
    SomeClass someClass;

    @Mock
    ClassA mockClassA;

    @Before
    public void inti() {
        someClass = PowerMockito.spy(new SomeClass());
    }

    @Test
    public void test() throws Exception {
        // To mock MyFactory.staticMethod();
        PowerMockito.mockStatic(MyFactory.class);
        Mockito.when(MyFactory.staticMethod()).thenReturn(mockClassA);
        // To mock helperMethod(id);
        PowerMockito.when(someClass, "helperMethod", Mockito.anyString())
                .thenReturn("retrunString");
        // To mock ojbectA.methodA(str);
        Mockito.when(mockClassA.methodA(Mockito.anyString())).thenReturn(
                "retStr1");
        // To mock ojbectA.methodB(str);
        Mockito.when(mockClassA.methodB(Mockito.anyString())).thenReturn(
                "retStr2");
    }
}
om39a
  • 1,406
  • 4
  • 20
  • 39
  • I am working with powermock-easymock-1.4.9-full.jar which is powermock with easymock extension. From your import statements i see that you use powermock with mockito extension. I am restricted to use only the powermock with easymock estension. My bad, i should have mentioned upfront. What bothers me the most is that it works with IDE but not ANT. Any clue on why this could be happening? For the sake of curiosity i will try your solution and see if it works. – maverick Jun 04 '12 at 02:28
  • If you could post the actual source code, that might help.... it looks like you have changed the name of the test class to TestClass and so.. If you could give actual class and the log, that will help a lot... – om39a Jun 04 '12 at 10:31
  • @ om39a : I have posted the actual code. Let me know if something is not clear in it. – maverick Jun 07 '12 at 20:23