如何使用 String 和 class 作为参数为 EntityManger createNativeQuery 编写 Junit 测试用例

2022-01-14 00:00:00 mockito oracle java junit jpa
@Repository
public class DesignatorDaoImpl extends GenericDaoImpl implements DesignatorDao {

    @Autowired
    EntityManager em;

    public List<Designator> getDesignators(DesignatorRequestDTO dto) throws Exception {
        List<Designator> designatorsList = new ArrayList<>();
        int start = dto.getStart();
        String queryString ="select * from ( SELECT * FROM TAB.DESIGNATOR WHERE ACTIVE_IND ='A' ORDER BY LAST_EDITED_DATE DESC ) OFFSET "+ start +" ROWS FETCH NEXT "+dto.getLimit()+" ROWS ONLY";          
        Query query = em.createNativeQuery(queryString,Designator.class);
        designatorsList = query.getResultList();
        return designatorsList;
    }
}

我有上面的类来从数据库中获取记录.我为上面的这个类编写了 JUnit 测试

I have the above class to get records from DB. I wrote JUnit test for this above class as

@Transactional
@Rollback(true)
public class DesignatorDaoImplTest {

    @Mock
    EntityManager entityManagerMock;

    @Mock
    TypedQuery<Designator> getQuery;

    @InjectMocks
    DesignatorDaoImpl designatorDaoImpl;

    DesignatorRequestDTO dto = new DesignatorRequestDTO();

    List<Designator> designatorEntityList = new ArrayList<>();

    @Before
    public void setUp() throws Exception { 
        MockitoAnnotations.initMocks(this);
        dto.setLimit(4);
        dto.setStart(1);

        Designator entity = new Designator();
        entity.setId("dgbkk");
        designatorEntityList.add(entity);
    }

    @Test
    public void saveDesignatorTest() throws Exception {
        Mockito.when(entityManagerMock.createNamedQuery(ArgumentMatchers.anyString(), ArgumentMatchers.eq(Designator.class))).thenReturn(getQuery);
        Mockito.when(getQuery.getResultList()).thenReturn(designatorEntityList);
        assertNotNull(designatorDaoImpl.saveDesignators(dto));
    }
}

我在模拟时遇到问题,在 dao 类中的这个 em.createNativeQuery(queryString,Designator.class) 中,我得到了 null.如何在测试类中正确模拟 em.createNativeQuery?

I have problem mocking and at this em.createNativeQuery(queryString,Designator.class) in dao class I am getting null. How can I properly mock the em.createNativeQuery in test class?

推荐答案

根据文档,如果你使用参数匹配器,所有参数都必须由匹配器提供.因此,请尝试使用 ArgumentMatchers.eq() (参考文档) 检查 Designator.class 是否相等:

According to the documentation, if you are using argument matchers, all arguments have to be provided by matchers. Hence, try using ArgumentMatchers.eq() (reference documentation) to check for Designator.class equality:

@Mock
TypedQuery<Designator> getQuery;

@Test
public void saveDesignatorTest() throws Exception {
    Mockito.when(entityManagerMock.createNamedQuery(ArgumentMatchers.anyString(), ArgumentMatchers.eq(Designator.class))).thenReturn(getQuery);
    Mockito.when(getQuery.getResultList()).thenReturn(designatorEntityList);
    assertNotNull(designatorDaoImpl.getDesignators(dto));
}


避免使用属性注入,而是使用构造函数注入:


Avoid using property injection and use constructor injection instead:

@Repository
public class DesignatorDaoImpl extends GenericDaoImpl implements DesignatorDao {

    private EntityManager em;

    public DesignatorDaoImpl(EntityManager em) {
        super();
        this.em = em;
    }

    public List<Designator> getDesignators(DesignatorRequestDTO dto) throws Exception {
        List<Designator> designatorsList = new ArrayList<>();
        int start = dto.getStart();
        String queryString ="select * from ( SELECT * FROM TAB.DESIGNATOR WHERE ACTIVE_IND ='A' ORDER BY LAST_EDITED_DATE DESC ) OFFSET "+ start +" ROWS FETCH NEXT "+dto.getLimit()+" ROWS ONLY";          
        Query query = em.createNativeQuery(queryString,Designator.class);
        designatorsList = query.getResultList();
        return designatorsList;
    }
}

然后您需要删除 @InjectMocks 因为您在初始化之前注入它们并创建 DesignatorDaoImpl 的实例以在 @Before 方法:

Then you need to drop @InjectMocks because you are injecting them before being initialized and create the instance of DesignatorDaoImpl to test in the @Before method:

@Transactional
@Rollback(true)
public class DesignatorDaoImplTest {

    @Mock
    EntityManager entityManagerMock;

    @Mock
    TypedQuery<Designator> getQuery;

    DesignatorDaoImpl designatorDaoImpl;

    DesignatorRequestDTO dto = new DesignatorRequestDTO();
    List<Designator> designatorEntityList = new ArrayList<>();

    @Before
    public void setUp() throws Exception { 
        MockitoAnnotations.initMocks(this);
        
        dto.setLimit(4);
        dto.setStart(1);

        Designator entity = new Designator();
        entity.setId("dgbkk");
        designatorEntityList.add(entity);

        designatorDaoImpl = new DesignatorDaoImpl(entityManagerMock);
    }

    @Test
    public void saveDesignatorTest() throws Exception {
        Mockito.when(entityManagerMock.createNamedQuery(ArgumentMatchers.anyString(), ArgumentMatchers.eq(Designator.class))).thenReturn(getQuery);
        Mockito.when(getQuery.getResultList()).thenReturn(designatorEntityList);
        assertNotNull(designatorDaoImpl.saveDesignators(dto));
    }
}


如果你不能改变 DesignatorDaoImpl 然后使用 @RunWith(MockitoJUnitRunner.class) 而不是 MockitoAnnotations.initMocks(this);as如下:


If you can't change DesignatorDaoImpl then use @RunWith(MockitoJUnitRunner.class) instead of MockitoAnnotations.initMocks(this);as follows:

@Transactional
@Rollback(true)
@RunWith(MockitoJUnitRunner.class)
public class DesignatorDaoImplTest {

    @Mock
    EntityManager entityManagerMock;

    @Mock
    TypedQuery<Designator> getQuery;

    @InjectMocks
    DesignatorDaoImpl designatorDaoImpl;

    DesignatorRequestDTO dto = new DesignatorRequestDTO();

    List<Designator> designatorEntityList = new ArrayList<>();

    @Before
    public void setUp() throws Exception { 
        MockitoAnnotations.initMocks(this);
        dto.setLimit(4);
        dto.setStart(1);

        Designator entity = new Designator();
        entity.setId("dgbkk");
        designatorEntityList.add(entity);
    }

    @Test
    public void saveDesignatorTest() throws Exception {
        Mockito.when(entityManagerMock.createNamedQuery(ArgumentMatchers.anyString(), ArgumentMatchers.eq(Designator.class))).thenReturn(getQuery);
        Mockito.when(getQuery.getResultList()).thenReturn(designatorEntityList);
        assertNotNull(designatorDaoImpl.saveDesignators(dto));
    }
}

相关文章