Most of these are not recommendable practices. Powermock is being replaced by Mockito 2.0, and the reflection tricks should be avoided. However we may happen to need them due to working with legacy code.
Let’s suppose we have taht kind of class with several issues such as this excerpt:
publicclassCTProcessConfigimplementsProcessEngineLookup { privatestaticfinalStringTENANT="TENANT"; // a private variable we can not modify as there is no setter privateStringprivateName="DUMMY_SERVICE"; private Map<String, ProcessEngine> storage; privatestatic DataSource datasource; publicCTProcessConfig() { storage = newHashMap<>(); initializeStorage(); } // this is an static method publicstatic DataSource getDatasource() { if (datasource == null) { try { // this is a constructor call, we can't mock it with Mockito datasource = (DataSource) newInitialContext().lookup( PROCESS_ENGINE_JNDI_SOURCE); } catch (NamingException e) { thrownewIOException("Unable to construct the datasource", e); } } return datasource; }
//this is a private method which can't be tested on its own @Override private TransactionManager lookupTransactionManager() { try { // this is an static method call, we can't mock it with Mockito return InitialContext .doLookup(WEB_LOGIC_TRANSACTION_MANAGER_BEAN_NAME); } catch (NamingException e) { throw ClinicalTrialException .create("Unable to lookup transaction manager", e); } } }
// use the powermock runner // do not forget to add the problematic static class on prepare with @RunWith(PowerMockRunner.class) @PrepareForTest({ InitialContext.class }) publicclassCTProcessConfigTest {
// a private variable we can not modify privateStringprivateName="DUMMY_SERVICE"; // instance to test private CTProcessConfig instance; // Mockito mocks @Mock private InitialContext initialContext; @Mock private TransactionManager transactionManager; @Mock private Datasource datasource; @Before publicvoidsetUp()throws NamingException { initInitialContext(); // initialize your instance for tests instance = newCTProcessMultiengineConfig(); } privatevoidinitInitialContext()throws NamingException { // mock the static PowerMockito.mockStatic(InitialContext.class); // treat it like a normal mockito mock Mockito.when(InitialContext.doLookup(Matchers.anyString())) .thenReturn(transactionManager); } }
How to test a private method
This is not a recommended, but there are cases when private methods are overwritten, so they are not easy to test individually. Let’s suppose we want to test the lookupTransactionManager method on its own. We can’t as it is private, hence we can use reflection to get it, make it accesible, and then set it back to its original state.