Search code examples
javaspring-bootunit-testingmockitojunit5

@InjectMocks injects new Instance instead of using defined Mock


I have a test where a repository mock should be inserted via DI in service and somehow Mockito makes new instance and injects wrong mock into service. My Repository class looks as followed:

@Repository 
public interface SomeRepository extends JpaRepository<Vorgang, Long> {
   Optional<SomeClass> findById(Long id);
}

Service class:

@RequiredArgsConstructor
@Service
public class SomeServiceImpl implements SomeService {
   

    private final SomeRepository someRepository;
    private final SomeMapper someMapper; 
    public SomeDTO getById(Long id) {
        return this. someRepository //
                .findById(id) //
                .map(this. someMapper::mapToDto) //s
                .orElseThrow(() -> new RequestException("Entity not found Id");
    }

And unit test is:

@SpringBootTest(classes = {SomeMapperImpl.class, OtherMapperImpl.class})
@ExtendWith({SpringExtension.class, MockitoExtension.class})
class SomeServiceTest {
    @Mock
    private SomeRepository someRepository;
    @Spy
    private SomeMapperImpl someMapper;

    @InjectMocks
    private SomeServiceImpl someService;

   @Test
    void testGetVorgangById_ValidId() {
        when(this.someRepository.findById(1L)).thenReturn(Optional.of(someObject));
        SomeDto someById = this.someService.getById(1L);
        ....
    }
}

I'm getting the exception because my repository mock doesn't return an object I want. I've tried to debug and compare objects using repository mock and mapper before calling service method and it works as it should. In a debugger I see that only the injected repository instance is not the one which should be injected, mapper instance is correct. Somehow Mockito inserts a new instance of my repository.

EDIT: Manual injection works correctly,

@BeforeEach
void setUp() {
  this.someService = new SomeService(someRepository, someMapper);
  ...
}

but @InjectMocks doesn't inject mocks as it should. What could be the problem?


Solution

  • Thanks knittl for the solution.

    In my case I had to manually inject all mocks beacuse @SpringBootTest and MockitoExtention are incompatible.

    This code worked for me:

    @SpringBootTest(classes = {SomeMapperImpl .class})
    class SomeServiceTest {
        @Mock
        private SomeRepository someRepository;
        @Spy
        private SomeMapperImpl someMapper;
    
        private SomeService someService;
    
        @BeforeEach
        void setUp() {
            this.someService= new SomeServiceImpl (someRepository, someMapper);
        }
        @Test
        void testGetVorgangById_ValidId() {
            when(this.someRepository.findById(1L)).thenReturn(Optional.of(someObject));
            SomeDto someById = this.someService.getById(1L);
            ....
        }
    }