Search code examples
javaspringjunitmockitospring-ldap

Ldap Unit Test Mock NamingEnumeration


I'm having trouble trying to mock the NamingEnumeration. Also, I cannot get the coverage to go inside of the lambda expression. I also cannot get the coverage inside of the while loop. When I run a unit test through the methods, coverage only shows through the ldapTemplate.search and it skips what's inside the lambda expression and it goes through the return list. I tried adding the Mock annotation to the NamingEnumeration and Attribute objects. 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();

This is my Ldap method

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

This is the Unit Test

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

Solution

  • I'm having trouble trying to mock the NamingEnumeration.

    Consider using a real enumeration instead. Basically you should only mock objects that are to complex to create yourself (Lists, Iterators and Enumeration are examples for things that are not).

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

    It works as expected. You mocked (read replaced) the search method, so there is no evaluation of the lambda expression as it already has a defined result.

    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 and next are typos on your end as the methods called in your example that are called are hasMoreElements and nextElement.

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

    You could verify the lambda expression seperately, example see below:

    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
    }