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!
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.