Search code examples
javajunitmockito

Argument passed to verify is not a Mock


I'm new to writing tests in Java and trying to learn Mockito.

This is part of the class I want to test.

public class ExamRepository implements IExamRepository {
    private static final Logger LOGGER = LogManager.getLogger(ExamRepository.class);

    private IStudentRepository studentRepository = new StudentRepository();
    private EntityManager entityManager;

    public ExamRepository() {
        entityManager = EntityController.getEntityManager();
    }

    public ExamRepository(EntityManager entityManager){
        this.entityManager = entityManager;
    }

    // Get all exam skeletons from the DB
    @Override
    public List<ExamSkeleton> getAllSkeletons() {
        try {
            TypedQuery<ExamSkeleton> query = entityManager.createQuery("SELECT NEW ExamSkeleton (s.id, s.filename, s.course, s.visible) FROM ExamSkeleton as s", ExamSkeleton.class);

            return query.getResultList();
        } catch (IllegalArgumentException exception) {
            LOGGER.error(exception);
        }

        return Collections.emptyList();
    }
}

This is the actual test I wrote, I have a feeling the error: Argument passed to verify() is of type ExamRepository and is not a mock!

Is occurring because of this line:

examRepository = new ExamRepository(entityManager);

However I am uncertain as to how to rewrite it. I am also not sure what else I should be testing for except for the fact that it ran once.

public class ExamRepositoryTest {
    @InjectMocks
    private ExamRepository examRepository;

    @Mock
    private EntityManager entityManager;

    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Test
    public void canGetAllSkeletons(){
        examRepository = new ExamRepository(entityManager);

        List<ExamSkeleton> examSkeletons = new ArrayList<>();
        examSkeletons.add(new ExamSkeleton());
        examSkeletons.add(new ExamSkeleton());

        TypedQuery query = mock(TypedQuery.class);
        when(entityManager.createQuery(anyString(), Matchers.anyObject())).thenReturn(query);
        when(query.getResultList()).thenReturn(examSkeletons);

        verify(examRepository, times(1)).getAllSkeletons();
    }
}

Hope you guys can put me on the correct track!


Solution

  • Use it like this:

    @Test
    public void canGetAllSkeletons(){
        examRepository = new ExamRepository(entityManager);
    
        List<ExamSkeleton> expected = new ArrayList<>();
        expected.add(new ExamSkeleton());
        expected.add(new ExamSkeleton());
    
        TypedQuery query = mock(TypedQuery.class);
        when(entityManager.createQuery(anyString(), anyObject())).thenReturn(query);
        when(query.getResultList()).thenReturn(expected);
    
        List<ExamSkeleton> result = examRepository.getAllSkeletons();
    
        assertEquals(expected, result);
    }
    

    Your idea was almost correct, but instead of verifying a call, you just need to do the actual invocation of examRepository.getAllSkeletons() in your test and check the result against your expected return value for the TypedQuery.

    And because you can only get the correct result list if your previous mocking steps worked, you don't need to verify any invocation on the EntityManager mock.