Issue
I stuck since a couple of hours on a test method.
I tried to reproduce a similar situation. I have a service who extend a abstract service with a utility method like this:
public class MyService extends MyAbstractService {
@Autowired
private UserRepository userRepository;
public void whatever(MyDTO myDTO) {
User user = this.userRepository.findByName(myDTO.userId);
hello(user.name);
}
}
abstract class MyAbstractService {
protected void hello(String userName) {
System.out.printf("Hello %s", userName);
}
}
my testing class :
@Test
void whenIcallWhaterver() {
MyService myService = Mockito.mock(MyService.class, InvocationOnMock::callRealMethod);
myService.whatever(myDTO);
verify(myService, only()).hello(anyString());
}
My goal is just to verify if when I go into the method whatever, the method of the abstract service is called too. I got a null pointer exception because the repository isn't not init in the mock (normal behavior I assume), but I would like to learn/understand how test this.
How could I do to fix this?
Thanks for your help
Solution
You are getting a NullPointerException because you are not setting an UserRepository object to MyService.
Note that your test does not load any spring context, so the annotation @Autowired is not taking effect.
So in order to get your test to work either:
- add a mock UserRepository to your service via constructor or setter
- or load a spring context to your test and add a mock UserRepository.
For example, you could do something like the following:
@SpringBootTest(classes = MyTestConfig.class)
class MyTest {
@MockBean
private UserRepository userRepository;
@SpyBean
private MyService myService;
@Test
void whenIcallWhaterver() {
// Mocks the response of the userRepository
final User user = new User();
user.setName("my-name");
Mockito.when(this.userRepository.findByName(Mockito.anyString()))
.thenReturn(user);
final MyDTO myDTO = new MyDTO();
myDTO.setUserId("myid");
this.myService.whatever(myDTO);
verify(this.myService).hello("my-name");
}
@Configuration
static class MyTestConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
}
Answered By - Jordi Martínez
Answer Checked By - Clifford M. (JavaFixing Volunteer)