Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use partial mocking for private static methods in PowerMock?

From the examples on the PowerMock homepage, I see the following example for partially mocking a private method with Mockito:

@RunWith(PowerMockRunner.class) // We prepare PartialMockClass for test because it's final or we need to mock private or static methods @PrepareForTest(PartialMockClass.class) public class YourTestCase { @Test public void privatePartialMockingWithPowerMock() {             PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());      // use PowerMockito to set up your expectation     PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");      // execute your test     classUnderTest.execute();      // Use PowerMockito.verify() to verify result     PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1"); } 

However, this approach does not seem to work when the private method we wish to mock is static. I wish to create a partial mock of the below class, with the readFile method mocked:

package org.rich.powermockexample;  import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.List;  import static com.google.common.io.Files.readLines;  public class DataProvider {      public static List<String> getData() {         List<String> data = null;         try {             data = readFile();         } catch (IOException e) {             e.printStackTrace();         }         return data;     }      private static List<String> readFile() throws IOException {         File file = new File("/some/path/to/file");         List<String> lines = readLines(file, Charset.forName("utf-8"));         return lines;     }  } 

Please could someone let me know how this can be achieved?

like image 861
Rich Ashworth Avatar asked Mar 15 '12 12:03

Rich Ashworth


People also ask

Can we mock static private methods?

For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.

How do I use mock private PowerMock?

Method With No Arguments but With Return Value. As a simple example, let's mock the behavior of a private method with no arguments and force it to return the desired value: LuckyNumberGenerator mock = spy(new LuckyNumberGenerator()); when(mock, "getDefaultLuckyNumber"). thenReturn(300);

Can we mock static methods in Mockito?

Since static method belongs to the class, there is no way in Mockito to mock static methods.


2 Answers

After doing a bit more research, it seems that PowerMockito.spy() and PowerMockito.doReturn() are what is required here:

package com.richashworth.powermockexample;  import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner;  import java.util.ArrayList; import java.util.List;  import static org.junit.Assert.assertEquals;   @RunWith(PowerMockRunner.class) @PrepareForTest({DataProvider.class}) public class ResultsWriterTest {      private static List<String> mockData = new ArrayList<String>();     private ResultsWriter resultsWriter;      @BeforeClass     public static void setUpOnce() {         final String firstLine = "Line 1";         final String secondLine = "Line 2";         mockData.add(firstLine);         mockData.add(secondLine);     }      @Before     public void setUp() {         resultsWriter = new ResultsWriter();     }      @Test     public void testGetDataAsString() throws Exception {         PowerMockito.spy(DataProvider.class);         PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile");          final String expectedData = "Line 1\nLine 2\n";         final String returnedString = resultsWriter.getDataAsString();          assertEquals(expectedData, returnedString);     }  } 

For further details and the complete code listing, check out my blog post here: https://richashworth.com/post/turbocharge-your-mocking-framework-with-powermock/

like image 189
Rich Ashworth Avatar answered Sep 21 '22 02:09

Rich Ashworth


Test class:

@RunWith(PowerMockRunner.class) @PrepareForTest(DataProvider.class) public class DataProviderTest {      @Test     public void testGetDataWithMockedRead() throws Exception {         mockStaticPartial(DataProvider.class, "readFile");          Method[] methods = MemberMatcher.methods(DataProvider.class, "readFile");         expectPrivate(DataProvider.class, methods[0]).andReturn(Arrays.asList("ohai", "kthxbye"));         replay(DataProvider.class);          List<String> theData = DataProvider.getData();         assertEquals("ohai", theData.get(0));         assertEquals("kthxbye", theData.get(1));     }  } 

Class being tested (basically yours):

public class DataProvider {      public static List<String> getData() {         try {             return readFile();         } catch (IOException e) {             e.printStackTrace();             return null;         }     }      private static List<String> readFile() throws IOException {         File file = new File("/some/path/to/file");         return readLines(file, Charset.forName("utf-8"));     }  } 
like image 22
Dave Newton Avatar answered Sep 20 '22 02:09

Dave Newton