I am getting null pointer exceptions on my transaction template when I try to test my method that uses manual transactions. When I am running the application in Spring Boot it works as expected.
@Autowired
TransactionTemplate template;
public CompletableFuture<MyResultEntity> addToA(BInput input) {
return CompletableFuture
.supplyAsync(
() -> template.execute(status -> {
A a = aRepository.findOne(input.getA());
List<B> addedBs = saveBs(input.getB(), a);
return new MyResultEntity(a, addedBs);
}), MyCustomExecutor());
}
I have tried using a mock template and inject it like this:
@Mock
private TransactionTemplate transactionTemplate;
@InjectMocks
private MyClass myClass;
I have also tried annotating my test with:
@RunWith(SpringJUnit4ClassRunner.class)
When debugging this configuration the template is actually injected and is not null any more. But since I am interested in testing the actions in the transactions I do not wish to mock it so i use:
when(transactionTemplate.execute(Mockito.any())).thenCallRealMethod();
This throws a new null pointer exception though since the transaction template tries to use the TransactionManager and that is still null.
How can I unit test my method calls inside the the transaction template?
What I normally do is not to call the real method, but to just mock the real behavior instead. Calling the real method in the mock will fail, because a mock is not managed inside of springs injection context. Well, to be exact, you can make them exist inside the injection context by adding them to a test configuration (plain SpringMVC) or using @MockBean (spring boot). But still they are just injected as a dependency. But won't receive any dependencies. For unit tests this is most often the desired behavior.
So just do something like:
when(_transactionTemplate.execute(any())).thenAnswer(invocation -> invocation.<TransactionCallback<Boolean>>getArgument(0).doInTransaction(_transactionStatus));
_transactionStatus can be a mock itself to test the usage of the state inside the callback.
Mocking is what mocks are used for :)