PowerMock Static Spy

This post shows how to partially mock a class's static methods.

Code Example

See PowerMock Setup page to learn how to get started with PowerMock.

UnderTest.java
1|    package main;
2|    
3|    public class UnderTest {
4|        public void foo() {
5|            MockClass.foo();
6|            System.out.println("UnderTest!");
7|            MockClass.foo2();
8|        }
9|    }  
MockClass.java
1 |    package main;
2 |    
4 |    public class MockClass {
5 |        public static void foo() {
6 |            System.out.println("Mocked Method!");
7 |        }
9 |    
10|        public static void foo2() {
11|            System.out.println("foo2!");
12|        }
13|    }
StaticSpyTest.java
1 |    package test;
2 |    import main.*;
3 |    import org.junit.Test;
4 |    import org.junit.runner.RunWith;
5 |    import org.powermock.api.mockito.PowerMockito;
6 |    import org.powermock.core.classloader.annotations.PrepareForTest;
7 |    import org.powermock.modules.junit4.PowerMockRunner;
8 |    
9 |    @PrepareForTest(MockClass.class)
10|    @RunWith(PowerMockRunner.class)
11|    public class StaticSpyTest {
12|        @Test
13|        public void spyTest() {
14|            // Object under test
15|            UnderTest obj = new UnderTest();
16|    
17|            // Partial mock
18|            PowerMockito.spy(MockClass.class);
19|            PowerMockito.doNothing().when(MockClass.class);
20|            MockClass.foo();
21|    
22|            // Test
23|            obj.foo();
24|        }
25|    }
Console Output
UnderTest!
foo2!

Similar to the Static Mock post, the MockClass.java class is mocked, but only partially. MockClass.foo() is mocked, which is why the "Mocked Method!" is not displayed, but "foo2!" is displayed from MockClass.foo2() (UnderTest.java line 7).

The PowerMockito method calls (StaticSpyTest.java lines 18-19) that perform the partial mock are not so straightforward as they are with Mockito. Line 18 tells PowerMock that MockClass.java needs to be treated as a partial mock, and line 19 tells it to mock a specific method in MockClass.class. The additional line (line 20) specifies the specific static method to mock, which is not needed in Mockito, and can cause confusion to those unfamiliar with PowerMock.

Static Method Stub

What happens if the mocked method returns something? Similar to Mockito, PowerMock supports stubs, which are controlled return variables.

Referring to the same Code Example as above, with a few modifications, we can see how static method stubs work.

MockedClass.java
1|    package main;
2|    
3|    public class MockClass {
4|        public static String foo() {
5|            return "Mocked Value!";
6|        }
7|    }

The String "Mocked Value!" will not actually be returned.

UnderTest.java
1|    package main;
2|    
3|    public class UnderTest {
4|        public String foo() {
5|            return MockClass.foo();
6|        }
7|    }
StaticSpyUnderTest.java
1 |    package test;
2 |    
3 |    import main.*;
4 |    import org.junit.Assert;
5 |    import org.junit.Test;
6 |    import org.junit.runner.RunWith;
7 |    import org.powermock.api.mockito.PowerMockito;
8 |    import org.powermock.core.classloader.annotations.PrepareForTest;
9 |    import org.powermock.modules.junit4.PowerMockRunner;
10|   
11|   @PrepareForTest(MockClass.class)
12|   @RunWith(PowerMockRunner.class)
13|   public class StaticSpyTest {
14|       @Test
15|       public void spyTest() {
16|           // Object under test
17|           UnderTest obj = new UnderTest();
18|   
19|           // Partial mock
20|           PowerMockito.spy(MockClass.class);
21|           PowerMockito.doReturn("Stub value!").when(MockClass.class);
22|           MockClass.foo();
23|   
24|           // Test
25|           Assert.assertEquals("Stub value!", obj.foo());
26|       }
27|   }

The only difference here is that we use doReturn("Stub value!") instead of doNothing(), which tells PowerMock to return a specific value ("Stub value!") when MockClass.foo() is called. After executing this test we see that the test passes, with obj.foo() returning the expected value.

Comments

Popular posts from this blog

Mocking Super Class Method Invocations with PowerMock

Verifying Static Method Calls

Unit Testing a Singleton Using PowerMock