传递给verify的参数不是Mock对象。

6

我刚开始学习在Java中编写测试,并尝试学习Mockito。

这是我想要测试的类的一部分。

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();
    }
}

这是我写的真实测试,我感觉错误出在这里: 传递给verify()的参数类型是ExamRepository,不是模拟对象!
发生这个错误的原因可能是以下代码行:
examRepository = new ExamRepository(entityManager);

然而,我不确定如何重写它。我也不知道除了它能运行一次之外,还应该测试什么其他内容。

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();
    }
}

希望你们能让我走上正确的道路!

这段话与IT技术无关,可能需要更多上下文信息才能提供更准确的翻译。
1个回答

9

使用方法如下:

@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);
}

你的想法几乎正确,但是你只需要在测试中执行examRepository.getAllSkeletons()的实际调用,并将结果与预期的TypedQuery返回值进行比较,而不是验证调用。因为只有在前面的模拟步骤成功的情况下,你才能获得正确的结果列表,所以你不需要验证EntityManager模拟对象的任何调用。

谢谢。在发布帖子4个小时后,我实际上在得到一位同学的帮助后自己找到了答案。我的代码与你的完全一样,所以谢谢。你有关于如何学习使用Mockito进行测试删除功能的任何提示/链接吗? - Bjorn Pijpops
可能听起来有些疯狂,但是官方Mockito文档对我来说是一个很好的学习地方。 - Marcus K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接