Thursday, June 16, 2016

Mocking of generic types with PowerMock and Mockito

See the earlier post Mocking with PowerMock and Mockito how to use the PowerMock for mocking of static classes. Mocking of generic types demands some additional handling.

Let's consider an example of a class with static methods and generic types in API.

A class DbProcExecutor encapsulates execution of DB procedures.
The method DbProcExecutor.executeDbProc1 executes the dbProcedure, which receives one input argument:
public final class DbProcExecutor {
      public static <I, O> DbOperationResult<O> executeDbProc1(I input, DbProc1<I, O> dbProcedure) {  
            try {  
               return procedure.run(input);  
            }  
            catch(Exception e) {  
               LOG.error("DB opertaion failure", e);  
               return null;  
            }  
      }
}

An application calls to DbProcExecutor.executeDbProc1 with concrete types:
DbOperationResult<DbUser> dbResult = DbProcExecutor.executeDbProc1(  
      userId, new BaseDbProc1<Integer, DbOperationResult<DbUser>>() {  
            @Override  
             public DbOperationResult<DbUser> get() {  
                  //...  
            }  
      });  

For unit testing of the application code we need to mock the DB stuff. Namely, we should mock the DbProcExecutor methods.
The example shows a test, which mocks DbProcExecutor.executeDbProc1:

To take care on the static stuff:
1. The test class is annotated with @PrepareForTest
2. The class mock is creted in in the setup method
@PrepareForTest({DbProcExecutor.class})
public class TestController {
      @Before
      public void setUp() {
            PowerMockito.mockStatic(DbProcExecutor.class);
      }
      ...
}

Mocking the DbProcExecutor.executeDbProc1 in a way below causes the compilation errors:
when(DbProcExecutor.executeDbProc1(Mockito.anyObject(), Mockito.anyObject())).thenReturn(getResult);
The error:
The method thenReturn(DbOperationResult<Object>) in the type OngoingStubbing<DbOperationResult<Object>>
is not applicable for the arguments (DbOperationResult<DbUser>)  
The solution is to qualify the static method call of when with the result type according to the context, where the service is called:

Mockito.<DbOperationResult<DbUser>>when(DbProcExecutor.executeDbProc1(Mockito.anyObject(),Mockito.anyObject())).thenReturn(getResult);  

No comments :

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top