首页 > 解决方案 > 通过验证的参数不是模拟

问题描述

我是使用 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();
    }
}

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

标签: javajunitmockito

解决方案


像这样使用它:

@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 模拟上的任何调用。


推荐阅读