Using PowerMock to mock/stub static void method calls in JUnit.

 

原文在这里:http://tarunsapra.wordpress.com/2011/07/31/mocking-static-void-calls-with-powermock-junit/

Sometimes  you do come across snippets of code that prove to be tricky while writing their JUnit tests.  One such scenario is the case of static void call, though some people would argue to extract the static void call into a separate method but that is old-school. PowerMock junit runner lets you  even mock static void and normal static calls. Let us take a look at both approaches the old one and the new one which uses PowerMock.

Older Approach

 

01 public class MyAction {
02
03 public String performSearch() {
04
05 // some logic operations
06
07 // the detestable static call
08 staticCall();
09
10 return "Success";
11 }
12
13 protected void staticCall() {
14 // <strong>the static void method call</strong>
15 MyStatic.staticMethod();
16 }
17
18 }
19
20 class MyStatic {
21
22 public static void staticMethod() {
23 throw new NullPointerException("Bazinga!");
24
25 }
26
27 }

 

In the above code snippet we can see that the static void call is extracted out in a separated method, now while writing the JUnit test for MyAction java class we can have anonymous sub-class which overrides the staticCall() method with it’s own implementation to avoid calling this method. Below code snippet elucidates the overriding

01 public class MyActionTest {
02
03 MyAction action;
04
05 @Before
06 public void setUp() {
07 action = new MyAction(){
08 protected void staticCall() {
09
10 System.out.println("inside overridden method");
11 };
12 };
13 }

 

In the above snippet we can see that I have overridden the staticCall() method, now while executing the Junit test the super-class method containing the static call is never invoked and hence our purpose is solved of avoiding the static call. But the reason I don’t consider this approach clean is that our code should not be changed in order to  make our Junit tests easier to write. Junit test should test existing running code without the need of modifying the code to meet JUnit’s need.

Now lets use PowerMock to mock the static void calls.

 

01 @RunWith(PowerMockRunner.class)
02 @PrepareForTest(MyStatic.class)
03 public class MyActionTest {
04 MyAction action;
05
06 @Before
07 public void setUp() {
08 action = new MyAction();
09 }
10
11 @Test
12 public void testPerformSearch() {
13
14 PowerMockito.spy(MyStatic.class);
15 PowerMockito.doNothing().when(MyStatic.class);
16 MyStatic.staticMethod();
17 Assert.assertEquals("Success", action.performSearch());
18 }
19 }

 

In the above code we have used PowerMock’s spy feature to partially mock the object, once you partial mock the object you have to stub the behavior i.e. prepare some canned calls. Here the PowerMock’s ability lies in the below three statements

 

1 PowerMockito.spy(MyStatic.class);
2 PowerMockito.doNothing().when(MyStatic.class);
3 MyStatic.staticMethod();

 

First we partially mock the MyStatic Class, then in the second line the doNothing() method is used to specify that the A static method call by the class MyStatic should result in doing nothing. Now since the object is partially mocked thus we also need to specify the method whose invocation is canned by doNothing() method, we do this in the 3rd statement MyStatic.staticMethod() , thus now it’s more of record-playback pattern wherein we have initially recorded the doNothing() behavior and then played the MyStatic.staticMethod().

Conclusion   The PowerMock approach is best possible solution i could find for mocking static calls without changing actual code, if you have any other tricks up your sleeve do share them!

You can download the powermock mocktio jars zip from here

你可能感兴趣的:(Powermock)