Issue
My ServiceImpl
looks like this:
@Service
public class GuildUsersServiceImpl implements GuildUsersService {
@Autowired
private final GuildUsersRepository guildUsersRepository;
@Autowired
private GuildService guildService;
@Autowired
private UserService userService;
@Autowired
private GuildUserRoleTypeService guildUserRoleTypeService;
@Autowired
public GuildUsersServiceImpl(final GuildUsersRepository guildUsersRepository) {
this.guildUsersRepository = guildUsersRepository;
}
public GuildUsers create(GuildUsers guildUser) {
return this.guildUsersRepository.save(guildUser);
}
}
And my service test for create
looks like this:
@RunWith(SpringRunner.class)
public class GuildUsersServiceTest {
@Mock private GuildUsersRepository guildUsersRepository;
@Mock private UserService userService;
@Mock private GuildService guildService;
@Mock private GuildUserRoleTypeService guildUserRoleTypeService;
@InjectMocks private GuildUsersServiceImpl guildUsersService;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
@Test
public void createTest() {
GuildUsers guildUsers = mockGuildUsers();
when(guildUsersRepository.save(guildUsers)).thenReturn(guildUsers);
GuildUsers dbGuildUsers = guildUsersService.create(guildUsers);
assertEquals(dbGuildUsers.getId(),guildUsers.getId());
}
}
I am using jUnit4
. Despite using when(guildUsersRepository.save(guildUsers)).thenReturn(guildUsers);
in the test, I run into a Null Pointer Exception with the following trace:
java.lang.NullPointerException: Cannot invoke "com.project.entities.domain.GuildUsers.getId()" because "dbGuildUsers" is null
I suspect something is wrong with how I have mocked the @Autowired
classes. What needs to be done differently while mocking classes in the Test class ?
At the same time I want the services in the following test case to work as well :
@Test
public void createTest1() {
GuildUsers guildUsers = mockGuildUsers();
GuildUsersWithoutGuildIdRequestDTO guildUsersWithoutGuildIdRequestDTO = new GuildUsersWithoutGuildIdRequestDTO();
guildUsersWithoutGuildIdRequestDTO.setUserId(guildUsers.getUser().getId());
guildUsersWithoutGuildIdRequestDTO.setGuildUserRoleTypeId(guildUsers.getGuildUserRoleType().getId());
when(guildService.get(guildUsers.getGuild().getId())).thenReturn(Optional.of(guildUsers.getGuild()));
when(guildRepository.findById(any())).thenReturn(Optional.of(guildUsers.getGuild()));
when(userService.get(guildUsers.getUser().getId())).thenReturn(Optional.of(guildUsers.getUser()));
when(guildUsersRepository.findById(guildUsers.getId())).thenReturn(null);
when(guildUserRoleTypeService.get(guildUsers.getGuildUserRoleType().getId())).thenReturn(Optional.of(guildUsers.getGuildUserRoleType()));
when(guildUsersRepository.save(any())).thenReturn(guildUsers);
GuildUsersResponseDTO dbGuildUsersResponseDTO =
guildUsersService.create(guildUsers.getGuild().getId(),guildUsersWithoutGuildIdRequestDTO);
assertEquals(dbGuildUsersResponseDTO.getGuildUserRoleType(),guildUsers.getGuildUserRoleType());
}
Solution
I don't know why you did field injection as well as constructor injection at the same time. You should remove one of them first, for instance:
@Service
public class GuildUsersServiceImpl implements GuildUsersService {
//@Autowired - removed
private final GuildUsersRepository guildUsersRepository;
@Autowired
private GuildService guildService;
@Autowired
private UserService userService;
@Autowired
private GuildUserRoleTypeService guildUserRoleTypeService;
//@Autowired - removed
public GuildUsersServiceImpl(final GuildUsersRepository guildUsersRepository) {
this.guildUsersRepository = guildUsersRepository;
}
public GuildUsers create(GuildUsers guildUser) {
return this.guildUsersRepository.save(guildUser);
}
}
OR remove the constructor to add:
@Autowired
private final GuildUsersRepository guildUsersRepository;```
Answered By - Aman