Hi,
Below is the sample class that I was trying to
unit test using mocking framework wherein ApplicationUtil class is an abstract class with all the methods as static.
package com.ql2.reports.test;
import com.opensymphony.xwork2.ActionContext;
import com.ql2.common.IAppConstants;
import com.ql2.reports.ReportDataManager;
import com.ql2.util.ApplicationUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.ql2.reports.service.ReportsListLoader;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import static org.easymock.EasyMock.expect;
import static org.powermock.api.easymock.PowerMock.createStrictMock;
import static org.powermock.api.easymock.PowerMock.replay;
import static org.powermock.api.easymock.PowerMock.mockStatic;
@RunWith(PowerMockRunner.class)
@PrepareForTest( {ApplicationUtil.class, TestReportList.class} )
public class TestReportList {
private ActionContext mockAC = null;
private ActionContext mockAC2 = null;
@Before
public void before() throws Exception {
}
@Test
public void testMethod() throws Exception {
Map sessionMap = new HashMap();
sessionMap.put("wsg_props", ReportDataManager.getInstance().initializeWsgProps(IAppConstants.RPT_WSG_PROPERTIES));
mockAC = createStrictMock(ActionContext.class);
mockAC2 = createStrictMock(ActionContext.class);
mockAC.setContext(mockAC2);
expect(mockAC.getContext().getSession()).andReturn(sessionMap);
replay(mockAC);
replay(mockAC2);
InputStream is = Mockito.mock(InputStream.class);
mockStatic(ApplicationUtil.class);
expect(ApplicationUtil.getFileAsResourceStream(ReportsListLoader.class, "test")).andReturn(is).anyTimes();
ReportsListLoader reportsListLoader2 = new ReportsListLoader();
reportsListLoader2.getReports();
}
@After
public void after() throws Exception {
}
}
There is a method in the ApplicationUtil class as :
public static InputStream getFileAsResourceStream(@Nonnull Class inputClass,
String fileName) {
return inputClass.getClassLoader().getResourceAsStream(fileName);
}
So when unit tested, the InputStream returned is null, hence I tried to mock this method by passing some values to ensure it returns a non null InputStream instance, but even before it goes to test the same, the moment I add this line on the class level of test case: @PrepareForTest( {ApplicationUtil.class, TestReportList.class} ), it fails with below exception:
java.lang.IllegalStateException: Failed to transform class with name com.ql2.reports.test.TestReportList. Reason: 3
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:207)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:145)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:65)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:133)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:39)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:217)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:59)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:26)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:63)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:192)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
at javassist.bytecode.ByteArray.write16bit(ByteArray.java:40)
at javassist.bytecode.StackMapTable$Shifter.update(StackMapTable.java:744)
at javassist.bytecode.StackMapTable$Shifter.sameFrame(StackMapTable.java:720)
at javassist.bytecode.StackMapTable$Walker.stackMapFrames(StackMapTable.java:194)
at javassist.bytecode.StackMapTable$Walker.parse(StackMapTable.java:179)
at javassist.bytecode.StackMapTable$Shifter.doit(StackMapTable.java:714)
at javassist.bytecode.StackMapTable.shiftPc(StackMapTable.java:693)
at javassist.bytecode.CodeIterator.insertGap0(CodeIterator.java:676)
at javassist.bytecode.CodeIterator.insertGap(CodeIterator.java:636)
at javassist.bytecode.CodeIterator.insertGapCore(CodeIterator.java:467)
at javassist.bytecode.CodeIterator.insertGap(CodeIterator.java:413)
at javassist.expr.Expr.replace0(Expr.java:298)
at javassist.expr.FieldAccess.replace(FieldAccess.java:213)
at org.powermock.core.transformers.impl.MainMockTransformer$PowerMockExpressionEditor.edit(MainMockTransformer.java:267)
at javassist.expr.ExprEditor.loopBody(ExprEditor.java:197)
at javassist.expr.ExprEditor.doit(ExprEditor.java:90)
at javassist.CtClassType.instrument(CtClassType.java:1289)
at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:75)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:203)
... 30 more
I have the below JAR files that my
JUNIT needs:
easymock-3.0
easymock-3.0-tests
easymockclassextension
javassist-3.12.0.GA
junit-4.9
mockito-all-1.5
objenesis-1.2
powermock-easymock-1.4.10-full
Can you please suggest what might be going wrong when adding @PrepareForTest annotation.
Regards
Sangeeta