I’m trying to test a service that injects its dependencies with @Inject. But for some reason I can’t use InjectMocks for other dependencias inside the test. My service Example:
@Component
public class UpdateFileService {
@Inject
FolderRepository folderRepository;
@Inject
PermissionDTOConverter permissionConverter;
}
The PermissionDTOConverter is a class that I don’t want to stub.
So I want to make It to work like this:
public class UpdateFileSecurityServiceTest {
@Mock
private FolderRepository folderRepository;
@InjectMocks
private PermissionDTOConverter permissionDTOConverter;
@InjectMocks
private UpdateFileSecurityService service;
}
And whenever I try to test a method It throws a NullPointerException because It says that the DTO does not exists. But if I use construtor injection like this>
public class UpdateFileSecurityServiceTest {
@Mock
private FolderRepository folderRepository;
@InjectMocks
private PermissionDTOConverter permissionDTOConverter;
@InjectMocks
private UpdateFileSecurityService service;
@Before
public void setUp() {
service = new UpdateFileSecurityService(folderRepository, permissionDTOConverter);
}
}
6
Mockito is designed to inject dependencies into a single class instance that you want to test. The notion that you are injecting dependencies into a dependency is counter to the intent of Mockito. However, I’ve had some success with this.
Per javadoc for InjectMocks
Again, note that @InjectMocks will only inject mocks/spies created using the @Spy or @Mock annotation.
So, PermissionDTOConverter
must be annotated as a Spy
in order for InjectMocks
to inject the PermissionDTOConverter
into UpdateFileSecurityService
while also injecting dependencies into PermissionDTOConverter
.
@InjectMocks
@Spy
PermissionDTOConverter permissionDTOConverter;
Unfortunately, that is not enough to actually get it to inject because the permissionDTOConverter reference will be injected into the UpdateFileSecurityService instance before it is instantiated. This is where you enter the grey area of undefined behavior. You can work around this by instantiating the Spy yourself. Note that the Spy
annotation is retained even though you are instantiating and telling Mockito to wrap it in a Spy yourself.
@InjectMocks
@Spy
PermissionDTOConverter permissionDTOConverter = Mockito.spy(new PermissionDTOConverter());
It appears that you do not have to define the Spy inline so long as you create the object that you want to spy upon. So the following should also work.
@InjectMocks
@Spy
PermissionDTOConverter permissionDTOConverter = new PermissionDTOConverter();
In sum, the following could work for you.
public class UpdateFileSecurityServiceTest {
@InjectMocks
private UpdateFileSecurityService SUT;
@Mock
private FolderRepository folderRepository;
@InjectMocks
@Spy
private PermissionDTOConverter permissionDTOConverter = new PermissionDTOConverter();
@Before private void setUp() {
MockitoAnnotations.init(this);
}
}
2