- 浏览: 11981 次
- 性别:
- 来自: 北京
最新评论
There are a lot of mocking libraries for Java, out of which EasyMock is my favorite. It has been serving well for me until I had to unit test legacy code which did not completely adhere to IOC (inversion of control) principles and had a lot of static method calls and direct creation of service/helper objects instead of using dependency injection. Unfortunately EasyMock could not handle mocking of static methods and objects which were created directly in the class or method being tested along with some other limitations such handling final classes.
This forced me to use other mocking libraries until I encountered PowerMock. It provides all the ammunition (and more) in dealing with these issues and has nice integration with EasyMock.
Here I’ll show you how to use EasyMock with PowerMock in order to handle common mocking test cases which were not possible with EasyMock before.
Set Up.
First to use PowerMock with easymock you need PowerMock libraries.
Here is maven dependency list:
Code to be tested.
view rawSampleUtils.javaThis Gist brought to you by GitHub.
The Unit Tests.
I am creating 5 different tests in order to gradually show you how to test different scenarios with last one combining all into one test as an example of how everything can work together.
view rawSampleServiceTest.javaThis Gist brought to you by GitHub.
Update: Just encountered limitation with PowerMock (and probably with any other Mocking frameworks) that it cannot mock “java.lang.reflect.Method”. The workaround is to just declare inner class that has method you need to mock.
This forced me to use other mocking libraries until I encountered PowerMock. It provides all the ammunition (and more) in dealing with these issues and has nice integration with EasyMock.
Here I’ll show you how to use EasyMock with PowerMock in order to handle common mocking test cases which were not possible with EasyMock before.
Set Up.
First to use PowerMock with easymock you need PowerMock libraries.
Here is maven dependency list:
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-test-easymock-junit4</artifactId> <version>1.4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.0</version> <scope>test</scope> </dependency>
Code to be tested.
public class SampleService { private SampleServiceHelper sampleServiceHelper = new SampleServiceHelper(); public String method1(){ return "method1:" + SampleUtils.staticMethod(); //we will need to mock this static method call } public String method2(){ return "method2:" + sampleServiceHelper.helperMethod(); //we will need to mock this method call on global variable that is created during class initialization } public String method3(){ SampleServiceHelper2 sampleServiceHelper2 = new SampleServiceHelper2(); return "method3:" + sampleServiceHelper2.helperMethod(); //we will need to mock this method call on variable that is created within this method } public String method4(){ return "method4:" + privateMethod("someParam"); //we will partially mock this private method call } public String method5(){ return "method5:" + SampleUtils.staticMethod() + privateMethod("someParam") + sampleServiceHelper.helperMethod(); //we will mock all three calls in the last test } protected String privateMethod(String param){ return "privateMethod-" + param; } } view rawSampleService.javaThis Gist brought to you by GitHub. public final class SampleServiceHelper { public String helperMethod(){ return "helperMethod"; } } view rawSampleServiceHelper.javaThis Gist brought to you by GitHub. public class SampleServiceHelper2 { public String helperMethod(){ return "helperMethod"; } } view rawSampleServiceHelper2.javaThis Gist brought to you by GitHub. public class SampleUtils { private SampleUtils(){ } public static String staticMethod(){ return "staticMethod"; } }
view rawSampleUtils.javaThis Gist brought to you by GitHub.
The Unit Tests.
I am creating 5 different tests in order to gradually show you how to test different scenarios with last one combining all into one test as an example of how everything can work together.
import org.easymock.EasyMock; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; import org.powermock.api.easymock.PowerMock; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.core.classloader.annotations.PrepareForTest; //This is required for PowerMock to work. @RunWith(PowerMockRunner.class) //The following class are included in @PrepareForTest because: //- SampleUtils.class. So that PowerMock will handle static method calls. // Notice that even though SampleUtils has private constructor PowerMock can // still handle mocking it. // //- SampleServiceHelper. Because its declared as final class and EasyMock wont // be able to mock it. // //- SampleService.class. So that PowerMock could intercept creation // of SampleServiceHelper class. And could do partial mocking of // "privateMethod" private method. @PrepareForTest( {SampleUtils.class, SampleServiceHelper.class, SampleService.class} ) public class SampleServiceTest { @Test public void testMethod1() throws Exception{ //This will mock the SampleUtils static method calls. PowerMock.mockStatic(SampleUtils.class); //Just do plain "new" of SampleService here since we are not calling //any private method inthis test method that need to be partially mocked. SampleService sampleService = new SampleService(); //Here we are telling what should happens when SampleUtils.staticMethod() //gets called. We can use EasyMock to do the expectation even though PowerMock //is mocking the static method call. EasyMock.expect( SampleUtils.staticMethod() ).andReturn("mockedStaticMethod"); //We need to have PowerMock replay SampleUtils.just like its done //with SampleServiceHelper.class //We cannot use EasyMock in this case since it does not handle Class objects. PowerMock.replay(SampleUtils.class); //------ Do actually call the method to be tested and do necessary assertions. String result = sampleService.method1(); assertEquals( "method1:" + "mockedStaticMethod", result ); //------ Do necessary verification to make sure that all methods we expected //to be called are called //Verification of Class mocks need to go through PowerMock, just like in replay. PowerMock.verify(SampleUtils.class); } @Test public void testMethod2() throws Exception{ //Here are going to tell PowerMock to replace all calls to new SampleServiceHelper //in SampleService with sampleServiceHelperMock. Notice that even though SampleServiceHelper is final //we now can mock it using EasyMock because is included in @PrepareForTest declaration. //Powermock example says to use PowerMock.mock but this works as well. SampleServiceHelper sampleServiceHelperMock = EasyMock.createMock(SampleServiceHelper.class); //Here we tell PowerMock to intercept all creations of SampleServiceHelper PowerMock.expectNew(SampleServiceHelper.class).andReturn(sampleServiceHelperMock); //PowerMock requires us to call this. Otherwise it will fail to intercept call to //"new" SampleServiceHelper. Cant use EasyMock here since it does not support //mocking Class objects. PowerMock.replay(SampleServiceHelper.class); //We need to create SampleService after the above call because //SampleServiceHelper is created during SampleService initialization. //"method3" will show you that you dont need to do this when object to be mocked //is created inside method that is tested. // //Just do plain "new" of SampleService here since we are not calling any method in //this test method that need to be partially mocked. SampleService sampleService = new SampleService(); //We can use EasyMock to replay plain mocks. EasyMock.expect( sampleServiceHelperMock.helperMethod() ) .andReturn("mockedHelperMethod"); //Again since sampleServiceHelper is mocked with EasyMock, we can replay it with //EasyMock. EasyMock.replay(sampleServiceHelperMock); //------ Do actually call the method to be tested and do necessary assertions. String result = sampleService.method2(); assertEquals( "method2:" + "mockedHelperMethod", result ); //------ Do necessary verification to make sure that all methods we expected //to be called are called //Verification of Class mocks need to go through PowerMock, just like in replay. PowerMock.verify(SampleServiceHelper.class); EasyMock.verify(sampleServiceHelperMock); } @Test public void testMethod3() throws Exception{ //Here are going to tell PowerMock to replace call to new SampleServiceHelper2 //in SampleService with sampleServiceHelper2Mock. SampleServiceHelper2 sampleServiceHelper2Mock = EasyMock.createMock(SampleServiceHelper2.class); //Here we tell PowerMock to intercept all creations of SampleServiceHelper2 PowerMock.expectNew(SampleServiceHelper2.class).andReturn(sampleServiceHelper2Mock); //Here we dont need to create SampleService before calling //PowerMock.replay(SampleServiceHelper2.class), since SampleServiceHelper2 //is created inside method3. // //Just do plain "new" of SampleService here since we are not calling any method in //this test method that need to be partially mocked. SampleService sampleService = new SampleService(); //Called after creation of SampleService. PowerMock.replay(SampleServiceHelper2.class); //We can use EasyMock to replay plain mocks. EasyMock.expect( sampleServiceHelper2Mock.helperMethod() ) .andReturn("mockedHelperMethod"); //Again since sampleServiceHelper2Mock is mocked with EasyMock and we can replay it with //EasyMock. Notice that even though "sampleService" is partially mocked by PowerMock //we still can replay it using EasyMock. EasyMock.replay(sampleServiceHelper2Mock); //------ Do actually call the method to be tested and do necessary assertions. String result = sampleService.method3(); assertEquals( "method3:" + "mockedHelperMethod", result ); //------ Do necessary verification to make sure that all methods we expected //to be called are called //Verification of Class mocks need to go through PowerMock, just like in replay. PowerMock.verify(SampleServiceHelper2.class); EasyMock.verify(sampleServiceHelper2Mock); } @Test public void testMethod4() throws Exception{ //Since we want to mock "privateMethod" we need to //partially mock SampleService with PowerMock. // //Also notice that we are not calling createPartialMock with constructor //arguments (like in testMethod5) since method4 does not use SampleServiceHelper. SampleService sampleService = PowerMock.createPartialMock(SampleService.class, "privateMethod", new Class[]{String.class} ); PowerMock.expectPrivate(sampleService, "privateMethod", "someParam").andReturn("mockedPrivateMethod"); //Notice that even though "sampleService" is partially mocked by PowerMock //we still can replay it using EasyMock. EasyMock.replay(sampleService); //------ Do actually call the method to be tested and do necessary assertions. String result = sampleService.method4(); assertEquals( "method4:" + "mockedPrivateMethod", result ); //------ Do necessary verification to make sure that all methods we expected //to be called are called EasyMock.verify(sampleService); } @Test public void testMethod5() throws Exception{ //This will mock the SampleUtils static method calls. PowerMock.mockStatic(SampleUtils.class); //Here are going to tell PowerMock to replace calls to new SampleServiceHelper //in SampleService with sampleServiceHelperMock. SampleServiceHelper sampleServiceHelperMock = EasyMock.createMock(SampleServiceHelper.class); //Here we tell PowerMock to intercept all creations of SampleServiceHelper PowerMock.expectNew(SampleServiceHelper.class).andReturn(sampleServiceHelperMock); //PowerMock requires us to call this. Otherwise it will fail to intercept call to //"new" SampleServiceHelper. Cant use EasyMock here since it does not support //mocking Class objects. PowerMock.replay(SampleServiceHelper.class); //We need to create SampleService after the above call because //SampleServiceHelper is create during SampleService initialization //"method3" will show you that you dont need to do this when object to be mocked //is created inside method that is tested. // //Since we want to mock "privateMethod" (which is private) we need to //partially mock SampleService with PowerMock. // //Also notice that we are calling createPartialMock with constructor //arguments since plain createPartialMock wont "by default" invoke constructor and //do class initialization which will prevent us from initializing sampleServiceHelper //variable. SampleService sampleService = PowerMock.createPartialMock(SampleService.class, "privateMethod", new Class[]{String.class}, new Object[]{}, new Class[]{} ); PowerMock.expectPrivate(sampleService, "privateMethod", "someParam").andReturn("mockedPrivateMethod"); //Here we are telling what should happens when SampleUtils.staticMethod() //gets called. We can use EasyMock to do the expectation even though PowerMock //is mocking the static method call. EasyMock.expect( SampleUtils.staticMethod() ).andReturn("mockedStaticMethod"); //We need to have PowerMock replay SampleUtils.just like its done //with SampleServiceHelper.class PowerMock.replay(SampleUtils.class); //We can use EasyMock to replay plain mocks. EasyMock.expect( sampleServiceHelperMock.helperMethod() ) .andReturn("mockedHelperMethod"); //Again since sampleServiceHelper is mocked with EasyMock, we can replay it with //EasyMock. Notice that even though "sampleService" is partially mocked by PowerMock //we still can replay it using EasyMock. EasyMock.replay(sampleServiceHelperMock, sampleService); //------ Do actually call the method to be tested and do necessary assertions. String result = sampleService.method5(); assertEquals( "method5:" + "mockedStaticMethod" + "mockedPrivateMethod" + "mockedHelperMethod", result ); //------ Do necessary verification to make sure that all methods we expected //to be called are called //Verification of Class mocks need to go through PowerMock, just like in replay. PowerMock.verify(SampleUtils.class, SampleServiceHelper.class); EasyMock.verify(sampleServiceHelperMock, sampleService); } }
view rawSampleServiceTest.javaThis Gist brought to you by GitHub.
Update: Just encountered limitation with PowerMock (and probably with any other Mocking frameworks) that it cannot mock “java.lang.reflect.Method”. The workaround is to just declare inner class that has method you need to mock.
相关推荐
PowerMock 也是一个单元测试模拟...PowerMock 的目的就是在当前已经被大家所熟悉的接口上通过添加极少的方法和注释来实现额外的功能,目前,PowerMock 仅支持 EasyMock 和 Mockito。 标签:PowerMock 单元测试
离线安装包,亲测可用
easymock3.1最新帮助文档chm格式
powermock-easymock-junit-1.5.4.zip
powermock-easymock-junit-1.6.1.zip
这是单元测试的时候使用easymock和powerMock测试的时候的jar包 找了好久
easymockclassextension-3.0.jar org.easymock.classextension.EasyMock.
EasyMock 使用方EEasyMock 使用方法与原理剖析.rar
jar包,官方版本,自测可用
jar包,官方版本,自测可用
还在为找不到jar文件烦心吗,不用了到我空间来有你想要的,持续更新。。。 easymock.jar,easymockclassextension.jar
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
easymockclassextension-2.4.jar是一个很齐全的jar包,可以放心下载使用
什么时候需要Mock对象 什么是EasyMock EasyMock的优点和缺点 运行EasyMock需要的资源 EasyMock的基本使用步骤 什么是PowerMock 运行PowerMock需要的资源 PowerMock的扩展功能
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,亲测可用
PowerMock is a framework that extend other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static ...
EasyMock主要是为测试提供模拟数据,比如你可以模拟HttpServletRequest。