I have a problem to write JUnit Service Test shown below.
I only access UserService (Interface) and UserServiceImpl cannot be accessed from outside as it is private. This is my case.
I have a problem to call saveUser
method.
Here is the structure
src
├── main
│ └── java
│ └── com
│ ├── company
│ ├── service
│ ├── UserService.java
│ ├── impl
│ ├── UserServiceImpl.java (package-private)
└── test
└── java
└── com
└── company
├── UserServiceTest.java
Here is the UserService shown below
public interface UserService {
UserDTO saveUser(SignUpRequest signUpRequest);
}
Here is the save Method defined in UserServiceImpl
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Transactional
public UserDTO saveUser(SignUpRequest signUpRequest) {
...
return UserDTO.builder()
.username(signUpRequest.getUsername())
.firstName(signUpRequest.getFirstName())
}
}
Here is the UserServiceTest shown below
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldCreateUser() {
User user = new User();
...
when(userRepository.save(any(User.class))).thenReturn(user);
UserDTO savedUserDTO = userService.saveUser(signUpRequest); // Here is the issue
}
I get this issue shown below
org.mockito.exceptions.base.MockitoException:
Cannot instantiate @InjectMocks field named 'userService'! Cause: the type 'UserService' is an interface.
You haven't provided the instance at field declaration so I tried to construct the instance.
Examples of correct usage of @InjectMocks:
@InjectMocks Service service = new Service();
@InjectMocks Service service;
//and... don't forget about some @Mocks for injection :)
When I changed userService as shown below, I get this issue.
@Mock
private UserService userService;
java.lang.NullPointerException: Cannot invoke "com.backend.user.service.dto.UserDTO.getUsername()" because "savedUserDTO" is null
How can I fix it?
You can't instantiate an interface in Java
. While using @InjectMock
you tell Mockito to instantiate your object and inject your dependency, here UserRepository
.
The first approach is to use a concrete implementation of your interface. Check this link for more details.
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserServiceImpl userService;
@Test
void shouldCreateUser() {
}
}
Also the class under test is UserService so you can't the annotation Mock
on it.