Cannot instantiate @InjectMocks field named

2024, May 01    

현상

  • jenkins로 junit test실행할 때 에러 발생
  • intellij로 maven install했을 때는 발생하지 않는다.
Cannot instantiate @InjectMocks field named '' of type 'class '. 
You haven't provided the instance at field declaration so I tried to construct the instance. 
However the constructor or the initialization block threw an exception : null

코드

@Component
public class FileResourceRepository {
    private final Path fileStorageLocation;

    public FileResourceRepository(
        final String uploadDir
    ) {
        this.fileStorageLocation = Paths.get(uploadDir, "test").toAbsolutePath().normalize();
    }

    public void saveStorage(String filePath) {
        try {
            Files.createDirectories(fileStorageLocation.resolve(filePath));
        } catch (IOException e) {
            throw new FileSystemWriteException("Create test repository fails: " + filePath + " when storage created");
        }
    }
}

테스트 코드

@ExtendWith(MockitoExtension.class)
class FileResourceRepositoryTest {
	@InjectMocks
    private FileResourceRepository fileResourceRepository;

    @Mock
    private Path fileStorageLocation;

    private final String filePath = "/tmp/uploads";

    @BeforeEach
    void setup() {
        fileResourceRepository = new FileResourceRepository(filePath);
    }

    @Test
    void saveFileSystemWriteException() throws IOException {
        Resource resource = mock(Resource.class);
        when(resource.getInputStream()).thenReturn(mock(InputStream.class));

        Executable executable = () -> fileResourceRepository.save(FileMetaKey.sample(), resource);
        assertThrows(FileSystemWriteException.class, executable);
    }

원인

  • 에러 메시지만 보면, @InjectMocks로 선언한 fileResourceRepository를 초기화할 때 npe가 발생했다는 것
  • 테스트하려는 클래스에 정의한 생성자 주입과정 없이 초기화를 해서 발생한 것으로
  • https://4whomtbts.tistory.com/129

해결

  • @InjectMocks를 제거
  • initMocks(this); 추가해서 초기화하고
  • 생성자에 Mock객체를 주입
@ExtendWith(MockitoExtension.class)
class FileResourceRepositoryTest {
    private FileResourceRepository fileResourceRepository;

    @Mock
    private Path fileStorageLocation;

    private final String filePath = "/tmp/uploads";

    @BeforeEach
    void setup() {
        initMocks(this);
        fileResourceRepository = new FileResourceRepository(filePath);
    }