title: Spring service unit testing using mockito
body: <p>Until now answers from SO has been utterly satisfying for my problems. I'm learning unit testing with Junit and Mockito and I want to test my service class which is a part of my Spring web app. I read many tutorials and articles and I still have problems to write proper unit tests for my service layer. I would like to know answers for my questions, but first I paste some code:</p>
  
  <p><strong>Service class</strong>
  </p>
  
  <pre><code>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&lt;Role&gt; roles = new ArrayList&lt;Role&gt;();
      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!");
      }
  }
  }
  </code></pre>
  
  <p><strong>My unfinished test class</strong>
  </p>
  
  <pre><code>@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)); 
  }
  
  }
  </code></pre>
  
  <p><strong>Questions</strong>:</p>
  
  <ol>
  <li>What is the best way to make unit tests where I have methods in methods like in my service class? Can I test them separately like above? [I divided my code into few methods to have cleaner code]</li>
  <li>Is testRegisterNewAccount() good unit test for my service method? Test is green however I am not sure about it.</li>
  <li>I am getting failure in my testShouldSetRoleToAccount. What am I doing wrong?</li>
  <li>How to test checkIfUsernameExists?</li>
  </ol>
  
  <p>Maybe someone will help me with this because I spent a couple of days and I didn't make a progress :(</p>
  
  <hr>
  
  <p><strong>UPDATE</strong></p>
  
  <p><strong>Finished test class</strong></p>
  
  <pre><code>@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());
  }
  
  }
  </code></pre>