0

I'm new to JMockit and have successfully run a basic unit test using it. However, I'm stuck when attempting to mock a Spring LdapTemplate. The problem seems to be with the LdapQuery that is used by the LdapTemplate. Do I need to mock this as well?

JUnit Test

@RunWith(JMockit.class)
public class MyTest {

    @Mocked
    LdapTemplate mockLdapTemplate;

    @Test
    public void retrieveAccount_test() {

        Account acct = new Account();
        acct.setEmail("foobar@gmail.com");
        acct.setUserId("userA");
        final List<Account> expected = Arrays.asList(acct);

        new Expectations() {
            { 
              mockLdapTemplate.search(query().base(anyString).where(anyString)
                    .is("userA"), (AttributesMapper) any);
              result = expected;
            }
        };
        AccountService service = new AccountServiceImpl(mockLdapTemplate);
        Account account = service.retrieveAccount("userA");
        assertThat(account, is(notNullValue()));
    }
}

AccountService

public class AccountServiceImpl implements AccountService {

private LdapTemplate ldapTemplate;

@Autowired
public AccountServiceImpl(LdapTemplate ldapTemplate) {
    this.ldapTemplate = ldapTemplate;
}

@Override
public Account retrieveAccount(String userId) {
    LdapQuery query = query().base("ou=users").where("uid").is(userId);
    List<Account> list = ldapTemplate.search(query,
            new AccountMapper());
    if (list != null && !list.isEmpty()) {
        return list.get(0);
    }

    return null;
}

public class AccountMapper implements
        AttributesMapper<Account> {

    @Override
    public Account mapFromAttributes(Attributes attrs)
            throws NamingException {
        Account account = new Account();
        account.setEmail((String) attrs.get("mail").get());
        account.setUserId((String) attrs.get("uid").get());

        return account;
    }
}
}

(Leaving out the Account class since it should be self explanatory.)

If I replace mockLdapTemplate.search(query().base(anyString).where(anyString) .is("userA"), (AttributesMapper) any); with mockLdapTemplate.search((LdapQuery)withNotNull(), (AttributesMapper) any) the test passes (which is what I expect, but this more or less tells me the problem is with the LdapQuery parameter).

Thanks!

acvcu
  • 2,476
  • 10
  • 40
  • 56

1 Answers1

0

You already know the answer: the expectation should be recorded as

mockLdapTemplate.search((LdapQuery)withNotNull(), (AttributesMapper) any)

because this is the only mocked method being called from the unit under test. The argument matchers "any", "withNotNull()", etc. can only be used on calls to mocked methods, and LdapQuery was not mocked in the test.

Rogério
  • 16,171
  • 2
  • 50
  • 63
  • Okay. So I do need to mock LdapQuery? Can you provide any example of that? My test is in the is() method when I pass in the "userA" parameter. Essentially without that the test doesn't really test anything. – acvcu May 12 '15 at 17:53
  • You could mock `LdapQuery`, but that would get complicated; a possible alternative (depending on the availability of suitable "getters" in the query object) would be to capture the query object passed to the `search` method, using `qry = withCapture()` as the argument matcher (with a local variable `LdapQuery qry`). Another alternative is to write an integration test using Spring's `org.springframework.ldap.test` facilities. – Rogério May 12 '15 at 21:54
  • Thanks. I'll give that first one a try. – acvcu May 13 '15 at 13:28