javaspringspring-bootjunitmockito

Why does @InjectMocks in Java Spring return null in my test case for a service?


I am trying to write test cases for a service I have implemented for a controller in Spring. I have the following Service and Test classes.

StudentCourseRequestService:

import java.util.List;
import org.springframework.stereotype.Service;
import model.CourseRequest;
import repository.ICourseRequestRepository;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class StudentCourseRequestService implements IStudentCourseRequestService {

    private final ICourseRequestRepository courseRequestRepository;

    @Override
    public boolean requestCourse(CourseRequest courseRequest) {
        return courseRequestRepository.saveRequest(courseRequest);
    }

    @Override
    public List<CourseRequest> getAllCourseRequests() {
        return courseRequestRepository.getAllCourseRequests();
    }

    @Override
    public List<CourseRequest> getAllCourseRequestsOfStudent(Long studentId) {
        return courseRequestRepository.getCourseRequestsByStudentId(studentId);
    }
    
}

Test class:

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import static org.assertj.core.api.Assertions.assertThat;
import model.CourseRequest;
import repository.ICourseRequestRepository;

public class StudentCourseRequestServiceTests {
    @MockBean
    private ICourseRequestRepository courseRequestRepository;

    @InjectMocks
    private StudentCourseRequestService studentCourseRequestService;

    @Test
    public void requestValidCourse() throws Exception {
        final CourseRequest courseRequest = new CourseRequest(
            "data0",
            "data1",
            "data2",
            "data3",
            "data4",
            "data5"
        );

        Mockito.when(courseRequestRepository.saveRequest(courseRequest)).thenReturn(true);
        boolean result = studentCourseRequestService.requestCourse(courseRequest);
        assertThat(result).isTrue();
    }
}

When I run the requestValidCourse() test case, I get the following error:

java.lang.NullPointerException: Cannot invoke "repository.ICourseRequestRepository.saveRequest(model.CourseRequest)" because "this.courseRequestRepository" is null
 at service.StudentCourseRequestServiceTests.requestValidCourse(StudentCourseRequestServiceTests.java:29)
 at java.base/java.util.ArrayList.forEach(Unknown Source)
 at java.base/java.util.ArrayList.forEach(Unknown Source)

How can I resolve this issue?


Solution

  • As @Lesiak recommended, I added the @ExtendWith(MockitoExtension.class) annotation to the top of the class, and changed courseRequestRepository to have the @Mock annotation, instead of the previous @MockBean annotation. The issue got resolved after these changes.

    Previously I had the configuration recommended by @Lesiak during my trials to resolve the issue, but I also had the annotation @ExtendWith(SpringExtension.class) at the top of the class. With this configuration, I got the same error. Removing the @ExtendWith(SpringExtension.class) annotation resolved the issue here.

    New test class:

    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.Mockito;
    import org.mockito.junit.jupiter.MockitoExtension;
    import static org.assertj.core.api.Assertions.assertThat;
    import model.CourseRequest;
    import repository.ICourseRequestRepository;
    
    @ExtendWith(MockitoExtension.class)
    public class StudentCourseRequestServiceTests {
        @Mock
        private ICourseRequestRepository courseRequestRepository;
    
        @InjectMocks
        private StudentCourseRequestService studentCourseRequestService;
    
        @Test
        public void requestValidCourse() throws Exception {
            final CourseRequest courseRequest = new CourseRequest(
            "data0",
            "data1",
            "data2",
            "data3",
            "data4",
            "data5"
        );
    
            Mockito.when(courseRequestRepository.saveRequest(courseRequest)).thenReturn(true);
            boolean result = studentCourseRequestService.requestCourse(courseRequest);
            assertThat(result).isTrue();
        }
    }