Spring service unit testing using mockito

До сих пор ответы из SO были полностью удовлетворительными для моих проблем. Я изучаю модульное тестирование с помощью Junit и Mockito и хочу протестировать класс сервиса, который является частью моего веб-приложения Spring. Я прочитал много руководств и статей, но у меня все еще есть проблемы с написанием правильных модульных тестов для моего сервисного слоя. Я хотел бы получить ответы на свои вопросы, но сначала я вставлю немного кода:

Класс сервиса

public class AccountServiceImpl implements AccountService {

@Autowired
AccountDao accountDao, RoleDao roleDao, PasswordEncoder passwordEncoder, SaltSource saltSource;

@PersistenceContext
EntityManager entityManager;

public Boolean registerNewAccount(Account newAccount) {
    entityManager.persist(newAccount);
    newAccount.setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
    setRoleToAccount("ROLE_REGISTERED", newAccount);

    return checkIfUsernameExists(newAccount.getUsername());    
}

public void setRoleToAccount(String roleName, Account account) {
    List<Role> roles = new ArrayList<Role>();
    try {
        roles.add(roleDao.findRole(roleName));
    } catch(RoleNotFoundException rnf) {
        logger.error(rnf.getMessage());
    }
    account.setRoles(roles);
}

public Boolean checkIfUsernameExists(String username) {
    try {
        loadUserByUsername(username);
    } catch(UsernameNotFoundException unf) {
        return false;
    }
    return true;
}

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
    try {
        Account loadedAccount = accountDao.findUsername(username);
        return loadedAccount;   
    } catch (UserNotFoundException e) {
        throw new UsernameNotFoundException("User: " + username + "not found!");
    }
}
}

Мой незаконченный тестовый класс

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest {

private AccountServiceImpl accountServiceImpl;
@Mock private Account newAccount;
@Mock private PasswordEncoder passwordEncoder;
@Mock private SaltSource saltSource;
@Mock private EntityManager entityManager;
@Mock private AccountDao accountDao;
@Mock private RoleDao roleDao;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
    accountServiceImpl = new AccountServiceImpl();
    ReflectionTestUtils.setField(accountServiceImpl, "entityManager", entityManager);
    ReflectionTestUtils.setField(accountServiceImpl, "passwordEncoder", passwordEncoder);
    ReflectionTestUtils.setField(accountServiceImpl, "saltSource", saltSource);
    ReflectionTestUtils.setField(accountServiceImpl, "accountDao", accountDao);
    ReflectionTestUtils.setField(accountServiceImpl, "roleDao", roleDao);
}

@Test
public void testRegisterNewAccount() {
    Boolean isAccountCreatedSuccessfully = accountServiceImpl.registerNewAccount(newAccount);

    verify(entityManager).persist(newAccount);
    verify(newAccount).setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
    assertTrue(isAccountCreatedSuccessfully);
}

@Test
public void testShouldSetRoleToAccount() throws RoleNotFoundException{
    Role role = new Role(); //Maybe I can use mock here?
    role.setName("ROLE_REGISTERED");
    when(roleDao.findRole("ROLE_REGISTERED")).thenReturn(role);
    accountServiceImpl.setRoleToAccount("ROLE_REGISTERED", newAccount);
    assertTrue(newAccount.getRoles().contains(role)); 
}

}

Вопросы:

  1. Какой лучший способ сделать модульные тесты, где у меня есть методы в методах, как в моем классе сервиса? Могу ли я тестировать их отдельно, как описано выше? [Я разделил свой код на несколько методов, чтобы код был чище]
  2. Является ли testRegisterNewAccount() хорошим модульным тестом для моего метода сервиса? Тест зеленый, но я не уверен в нем.
  3. Я получаю ошибку в testShouldSetRoleToAccount. Что я делаю не так?
  4. Как проверить checkIfUsernameExists?

Может кто-нибудь поможет мне с этим, потому что я потратил пару дней и не продвинулся :(


UPDATE

Закончил тестирование класса

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest extends BaseTest {

private AccountServiceImpl accountServiceImpl;
private Role role;
private Account account;
@Mock private Account newAccount;
@Mock private PasswordEncoder passwordEncoder;
@Mock private SaltSource saltSource;
@Mock private EntityManager entityManager;
@Mock private AccountDao accountDao;
@Mock private RoleDao roleDao;

@Before
public void init() {
    accountServiceImpl = new AccountServiceImpl();
    role = new Role();
    account = new Account();
    ReflectionTestUtils.setField(accountServiceImpl, "entityManager", entityManager);
    ReflectionTestUtils.setField(accountServiceImpl, "passwordEncoder", passwordEncoder);
    ReflectionTestUtils.setField(accountServiceImpl, "saltSource", saltSource);
    ReflectionTestUtils.setField(accountServiceImpl, "accountDao", accountDao);
    ReflectionTestUtils.setField(accountServiceImpl, "roleDao", roleDao);
}

@Test
public void testShouldRegisterNewAccount() {
    Boolean isAccountCreatedSuccessfully = accountServiceImpl.registerNewAccount(newAccount);

    verify(entityManager).persist(newAccount);
    verify(newAccount).setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
    assertTrue(isAccountCreatedSuccessfully);
}

@Test(expected = IllegalArgumentException.class)
public void testShouldNotRegisterNewAccount() {
    doThrow(new IllegalArgumentException()).when(entityManager).persist(account);
    accountServiceImpl.registerNewAccount(account);
}

@Test
public void testShouldSetRoleToAccount() throws RoleNotFoundException {
    when(roleDao.findRole(anyString())).thenReturn(role);
    accountServiceImpl.setRoleToAccount("ROLE_REGISTERED", account);
    assertTrue(account.getRoles().contains(role)); 
}

@Test
public void testShouldNotSetRoleToAccount() throws RoleNotFoundException {
    when(roleDao.findRole(anyString())).thenThrow(new RoleNotFoundException());
    accountServiceImpl.setRoleToAccount("ROLE_RANDOM", account);
    assertFalse(account.getRoles().contains(role));
}

@Test
public void testCheckIfUsernameExistsIsTrue() throws UserNotFoundException {
    when(accountDao.findUsername(anyString())).thenReturn(account);
    Boolean userExists = accountServiceImpl.checkIfUsernameExists(anyString());
    assertTrue(userExists);
}

@Test
public void testCheckIfUsernameExistsIsFalse() throws UserNotFoundException {
    when(accountDao.findUsername(anyString())).thenThrow(new UserNotFoundException());
    Boolean userExists = accountServiceImpl.checkIfUsernameExists(anyString());
    assertFalse(userExists);
}

@Test 
public void testShouldLoadUserByUsername() throws UserNotFoundException {
    when(accountDao.findUsername(anyString())).thenReturn(account);
    Account foundAccount = (Account) accountServiceImpl.loadUserByUsername(anyString());
    assertEquals(account, foundAccount);
}

@Test(expected = UsernameNotFoundException.class)
public void testShouldNotLoadUserByUsername() throws UserNotFoundException {
    when(accountDao.findUsername(anyString())).thenThrow(new UsernameNotFoundException(null));
    accountServiceImpl.loadUserByUsername(anyString());
}

}
12
задан Mariusz Grodek 26 January 2012 в 19:30
поделиться