Search code examples
javaspringunit-testingjunitjmockit

Using another object as parameter in Jmockit Mocked object


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!


Solution

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