Ldap 单元测试模拟 NamingEnumeration

Ldap Unit Test Mock NamingEnumeration

我在尝试模拟 NamingEnumeration 时遇到问题。此外,我无法覆盖到 lambda 表达式内部。我也无法获得 while 循环内的覆盖范围。当我 运行 通过这些方法进行单元测试时,覆盖率仅通过 ldapTemplate.search 显示,它会跳过 lambda 表达式中的内容,并通过 return 列表。我尝试将 Mock 注释添加到 NamingEnumeration 和 Attribute 对象。 while 循环似乎认为 NamingEnumeration 是空的,因为没有覆盖。

'Unnecessary stubbings detected in test class' 中的以下结果:doReturn(true,false).when(enumeration).hasMore();doReturn(attr).when(enumeration).next();

这是我的Ldap方法

public List<MyObject> ldapQueryList(final String ldapSearch, final String key) {
        List<MyObject> list = new ArrayList<>();

        ldapTemplate.search("ou=User Accounts", "cn=" + ldapSearch), (Attributes attrs) -> {
                NamingEnumeration<?> enumeration = attrs.get(key).getAll();
                list.addAll(addToList(enumeration));
                return attrs;
        });

        return list;
    }
    public List<MyObject> addToList(NamingEnumeration<?> enumeration) throws NamingException {
        List<MyObject> list = new ArrayList<>();
        while (enumeration.hasMoreElements()) {
            final MyObject myObj = new MyObject();
            final String str = (String)enumeration.nextElement();
            myObj.setMyString(str);
            list.add(myObj);    
        }
        enumeration.close();
        return list;
    }

这是单元测试

@RunWith(MockitoJUnitRunner.class)
public class LdapQueryDaoTest {
    @Mock
    private LdapTemplate ldapTemplate;
    @InjectMocks
    private LdapDao ldapDao;
    @Mock 
    private NamingEnumeration<?> enumeration;
    @Mock 
    private Attribute attr;
    @Test
    public void ldapQueryList() throws DataAcesExcp, NamingException {
        List<String> searchResult = Collections.singletonList("search result");
        when(ldapTemplate.search( Mockito.anyString(), Mockito.anyString(), ArgumentMatchers.<AttributesMapper<String>> any())).thenReturn(searchResult);
        List<EmployeeVo> responseEntity = ldapDao.ldapQueryList(Const.EMPLOYEE_ID, "myLdapObj");
        Assert.assertNotNull(responseEntity);
    }
    @Test
    public void addToList() throws NamingException {
        doReturn(true,false).when(enumeration).hasMore();
        doReturn(attr).when(enumeration).next();
        Assert.assertNotNull(ldapQueryDaoImpl.addToList(enumeration));
    }
}

I'm having trouble trying to mock the NamingEnumeration.

考虑改为使用真实枚举。基本上你应该只模拟那些你自己创建起来很复杂的对象(列表、迭代器和枚举是不复杂的例子)。

Also, I cannot get the coverage to go inside of the lambda expression.

它按预期工作。您模拟(读取替换)了搜索方法,因此没有对 lambda 表达式求值,因为它已经有定义的结果。

The while loop seem to think NamingEnumeration is empty, because of the no coverage.

The following results in 'Unnecessary stubbings detected in test class': doReturn(true,false).when(enumeration).hasMore(); and doReturn(attr).when(enumeration).next();

hasMore 和 next 是您这边的拼写错误,因为您的示例中调用的方法是 hasMoreElements 和 nextElement。

@Test
public void addToList() throws NamingException {
   doReturn(true,false).when(enumeration).hasMoreElements();
   doReturn(attr).when(enumeration).nextElement();
   Assert.assertNotNull(ldapQueryDaoImpl.addToList(enumeration));
}

您可以单独验证lambda表达式,示例如下:

class MyMatcher implements AttributesMapper<Attributes> {

    List<MyObject> list = new ArrayList<>();

    public Attributes mapFromAttributes(Attributes attrs) {

        NamingEnumeration<?> enumeration = attrs.get(key).getAll();
        list.addAll(addToList(enumeration));
        return attrs;
    }
}
public void test() {

  NamingEnumeration<? extends Attribute> enumeration = ...

  Attribute attributeMock = mock(Attribute.class);
  when(attributeMock.getAll()).thenReturn(enumeration);

  Attributes attributesMock = mock(Attributes.class);
  when(attributesMock.get(any(String.class)).thenReturn(attributeMock);

  MyMatcher matcher = new MyMatcher();
  matcher.mapFromAttributes(attr);

  // assert ... matcher.list
}