com.ushahidi.swiftriver.core.api.service.AccountServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for com.ushahidi.swiftriver.core.api.service.AccountServiceTest.java

Source

/**
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/agpl.html>
 * 
 * Copyright (C) Ushahidi Inc. All Rights Reserved.
 */
package com.ushahidi.swiftriver.core.api.service;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.ushahidi.swiftriver.core.api.auth.AuthenticationScheme;
import com.ushahidi.swiftriver.core.api.auth.crowdmapid.CrowdmapIDClient;
import com.ushahidi.swiftriver.core.api.dao.AccountDao;
import com.ushahidi.swiftriver.core.api.dao.ActivityDao;
import com.ushahidi.swiftriver.core.api.dao.ClientDao;
import com.ushahidi.swiftriver.core.api.dao.RoleDao;
import com.ushahidi.swiftriver.core.api.dao.UserDao;
import com.ushahidi.swiftriver.core.api.dao.UserTokenDao;
import com.ushahidi.swiftriver.core.api.dto.CreateAccountDTO;
import com.ushahidi.swiftriver.core.api.dto.CreateClientDTO;
import com.ushahidi.swiftriver.core.api.dto.GetAccountDTO;
import com.ushahidi.swiftriver.core.api.dto.GetActivityDTO;
import com.ushahidi.swiftriver.core.api.dto.GetClientDTO;
import com.ushahidi.swiftriver.core.api.dto.ModifyAccountDTO;
import com.ushahidi.swiftriver.core.api.exception.NotFoundException;
import com.ushahidi.swiftriver.core.mail.EmailHelper;
import com.ushahidi.swiftriver.core.mail.EmailType;
import com.ushahidi.swiftriver.core.model.Account;
import com.ushahidi.swiftriver.core.model.AccountFollower;
import com.ushahidi.swiftriver.core.model.Activity;
import com.ushahidi.swiftriver.core.model.ActivityType;
import com.ushahidi.swiftriver.core.model.Bucket;
import com.ushahidi.swiftriver.core.model.BucketActivity;
import com.ushahidi.swiftriver.core.model.Client;
import com.ushahidi.swiftriver.core.model.Form;
import com.ushahidi.swiftriver.core.model.FormActivity;
import com.ushahidi.swiftriver.core.model.River;
import com.ushahidi.swiftriver.core.model.RiverActivity;
import com.ushahidi.swiftriver.core.model.Role;
import com.ushahidi.swiftriver.core.model.User;
import com.ushahidi.swiftriver.core.model.UserToken;
import com.ushahidi.swiftriver.core.util.TextUtil;

public class AccountServiceTest {

    private Account account;

    private GetAccountDTO getAccountDTO;

    private AccountDao mockAccountDao;

    private UserDao mockUserDao;

    private UserTokenDao mockUserTokenDao;

    private ClientDao mockClientDao;

    private RoleDao mockRoleDao;

    private ActivityDao mockActivityDao;

    private Mapper mockMapper;

    private Mapper mapper;

    private AccountService accountService;

    private RiverService mockRiverService;

    private BucketService mockBucketService;

    private PasswordEncoder passwordEncoder;

    private CrowdmapIDClient mockCrowdmapIDClient;

    private EmailHelper mockEmailHelper;

    @Before
    public void setup() {
        account = new Account();
        account.setId(13);
        account.setOwner(new User());
        account.setFollowers(new ArrayList<AccountFollower>());
        account.setFollowing(new ArrayList<AccountFollower>());

        getAccountDTO = new GetAccountDTO();

        mockAccountDao = mock(AccountDao.class);
        mockUserDao = mock(UserDao.class);
        mockUserTokenDao = mock(UserTokenDao.class);
        mockClientDao = mock(ClientDao.class);
        mockRoleDao = mock(RoleDao.class);
        mockActivityDao = mock(ActivityDao.class);
        mockMapper = mock(Mapper.class);
        mapper = new DozerBeanMapper();
        passwordEncoder = new BCryptPasswordEncoder();
        when(mockMapper.map(account, GetAccountDTO.class)).thenReturn(getAccountDTO);
        mockRiverService = mock(RiverService.class);
        mockBucketService = mock(BucketService.class);
        mockCrowdmapIDClient = mock(CrowdmapIDClient.class);
        mockEmailHelper = mock(EmailHelper.class);

        accountService = new AccountService();
        accountService.setRiverService(mockRiverService);
        accountService.setBucketService(mockBucketService);
        accountService.setAccountDao(mockAccountDao);
        accountService.setMapper(mockMapper);
        accountService.setUserDao(mockUserDao);
        accountService.setUserTokenDao(mockUserTokenDao);
        accountService.setClientDao(mockClientDao);
        accountService.setRoleDao(mockRoleDao);
        accountService.setActivityDao(mockActivityDao);
        accountService.setPasswordEncoder(passwordEncoder);
        accountService.setEncryptionKey("2344228477#97{7&6>82");
        accountService.setAuthenticationScheme(AuthenticationScheme.DEFAULT);
        accountService.setCrowdmapIDClient(mockCrowdmapIDClient);
        accountService.setEmailHelper(mockEmailHelper);
    }

    @Test
    public void findById() throws NotFoundException {
        when(mockAccountDao.findById(anyLong())).thenReturn(account);

        GetAccountDTO actualGetAccountDTO = accountService.getAccountById(13L, "admin");

        verify(mockAccountDao).findById(13L);
        assertEquals(getAccountDTO, actualGetAccountDTO);
    }

    @Test
    public void findByUsername() throws NotFoundException {
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);

        GetAccountDTO actualGetAccountDTO = accountService.getAccountByUsername("admin");

        verify(mockAccountDao).findByUsernameOrEmail("admin");
        assertEquals(getAccountDTO, actualGetAccountDTO);
    }

    @Test
    public void findByName() throws NotFoundException {
        when(mockAccountDao.findByAccountPath(anyString())).thenReturn(account);

        GetAccountDTO actualGetAccountDTO = accountService.getAccountByAccountPath("default", "user1");

        verify(mockAccountDao).findByAccountPath("default");
        assertEquals(getAccountDTO, actualGetAccountDTO);
    }

    @Test
    public void findByEmail() throws NotFoundException {
        when(mockAccountDao.findByEmail(anyString())).thenReturn(account);

        GetAccountDTO actualGetAccountDTO = accountService.getAccountByEmail("email", "user1");

        verify(mockAccountDao).findByEmail("email");
        assertEquals(getAccountDTO, actualGetAccountDTO);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void mapGetAccountDTO() {
        // Set up mock behaviour for filtering accessible rivers
        List<River> filteredRivers = new ArrayList<River>();
        filteredRivers.add(new River());
        when(mockRiverService.filterVisible(anyList(), (Account) anyObject())).thenReturn(filteredRivers);

        // Set up mock behaviour for filtering accessible buckets
        List<Bucket> filteredBuckets = new ArrayList<Bucket>();
        filteredBuckets.add(new Bucket());
        when(mockBucketService.filterVisible(anyList(), (Account) anyObject())).thenReturn(filteredBuckets);

        GetAccountDTO mockAccountDTO = mock(GetAccountDTO.class);

        // Set up the mock account to be queried
        Account mockAccount = mock(Account.class);
        List<AccountFollower> followers = new ArrayList<AccountFollower>();
        List<AccountFollower> following = new ArrayList<AccountFollower>();
        following.add(new AccountFollower());

        when(mockAccount.getFollowers()).thenReturn(followers);
        when(mockAccount.getFollowing()).thenReturn(following);
        when(mockMapper.map((Account) anyObject(), any(Class.class))).thenReturn(mockAccountDTO);

        accountService.mapGetAccountDTO(mockAccount, account);

        verify(mockAccount).getRivers();
        verify(mockAccount).getCollaboratingRivers();
        verify(mockAccount).getFollowingRivers();
        verify(mockAccount).getBuckets();
        verify(mockAccount).getCollaboratingBuckets();
        verify(mockAccount).getFollowingBuckets();
        verify(mockMapper).map(mockAccount, GetAccountDTO.class);

    }

    @Test
    public void search() {
        AccountDao mockAccountDao = mock(AccountDao.class);
        List<Account> accounts = new ArrayList<Account>();
        accounts.add(account);
        when(mockAccountDao.search(anyString())).thenReturn(accounts);
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);
        accountService.setAccountDao(mockAccountDao);

        List<GetAccountDTO> getAccountDTOs = accountService.searchAccounts("abcd", "user1");

        verify(mockAccountDao).search("abcd");
        assertEquals(1, getAccountDTOs.size());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void createAccountForDefaultAuthentication() {
        when(mockMapper.map(any(Account.class), any(Class.class))).thenReturn(getAccountDTO);

        CreateAccountDTO createAccount = new CreateAccountDTO();
        createAccount.setAccountPath("account_path");
        createAccount.setAccountPrivate(true);
        createAccount.setEmail("email@example.com");
        createAccount.setName("account name");
        createAccount.setPassword("totally secret");

        GetAccountDTO actual = accountService.createAccount(createAccount);

        ArgumentCaptor<User> userArgument = ArgumentCaptor.forClass(User.class);
        verify(mockUserDao).create(userArgument.capture());

        User user = userArgument.getValue();
        assertEquals("email@example.com", user.getEmail());
        assertEquals("account name", user.getName());
        assertEquals("email@example.com", user.getUsername());
        assertTrue(passwordEncoder.matches("totally secret", user.getPassword()));

        ArgumentCaptor<UserToken> tokenArgument = ArgumentCaptor.forClass(UserToken.class);
        verify(mockUserTokenDao).create(tokenArgument.capture());
        verify(mockEmailHelper).sendAccountActivationEmail(userArgument.capture(), tokenArgument.capture());

        UserToken token = tokenArgument.getValue();
        assertEquals(user, token.getUser());
        assertNotNull(token.getToken());

        ArgumentCaptor<Account> accountArgument = ArgumentCaptor.forClass(Account.class);
        verify(mockAccountDao).create(accountArgument.capture());

        Account account = accountArgument.getValue();
        assertEquals("account_path", account.getAccountPath());
        assertTrue(account.isAccountPrivate());
        assertEquals(user, account.getOwner());

        assertEquals(getAccountDTO, actual);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void createAccountForCrowdmapIDAuthentication() {
        accountService.setAuthenticationScheme(AuthenticationScheme.CROWDMAPID);

        CreateAccountDTO createAccount = new CreateAccountDTO();
        createAccount.setAccountPath("account_path");
        createAccount.setAccountPrivate(true);
        createAccount.setEmail("email@example.com");
        createAccount.setName("account name");
        createAccount.setPassword("totally secret");

        String crowdmapIDUID = "0487fLPSOFKFL9484LAJFJGXBN";

        when(mockMapper.map(any(Account.class), any(Class.class))).thenReturn(getAccountDTO);

        when(mockCrowdmapIDClient.isRegistered(anyString())).thenReturn(Boolean.FALSE);
        when(mockCrowdmapIDClient.register(anyString(), anyString())).thenReturn(crowdmapIDUID);

        accountService.createAccount(createAccount);
        ArgumentCaptor<User> userArgument = ArgumentCaptor.forClass(User.class);
        ArgumentCaptor<UserToken> tokenArgument = ArgumentCaptor.forClass(UserToken.class);

        verify(mockCrowdmapIDClient).isRegistered("email@example.com");
        verify(mockCrowdmapIDClient).register("email@example.com", "totally secret");
        verify(mockEmailHelper).sendAccountActivationEmail(userArgument.capture(), tokenArgument.capture());
    }

    @Test
    public void modifyAccount() {
        accountService.setMapper(mapper);

        User user = new User();
        user.setActive(false);
        user.setExpired(true);
        user.setLocked(true);
        user.setId(1);
        user.setPassword("$2a$05$f0I9XjamKm4LEaF8av1Zy.tzBrzFM0smLMKvMAqUWicGAcEnkCdQe");

        Account account = new Account();
        account.setActive(false);
        account.setOwner(user);
        account.setFollowers(new ArrayList<AccountFollower>());
        account.setFollowing(new ArrayList<AccountFollower>());
        UserToken userToken = new UserToken();
        userToken.setUser(account.getOwner());
        userToken.setExpires(new Date((new Date()).getTime() + 86400000L));

        ModifyAccountDTO modifyAccount = new ModifyAccountDTO();
        modifyAccount.setAccountPath("new account path");
        modifyAccount.setAccountPrivate(true);
        modifyAccount.setRiverQuotaRemaining(999);
        modifyAccount.setToken("this is a token");

        ModifyAccountDTO.User owner = new ModifyAccountDTO.User();
        owner.setEmail("email@example.com");
        owner.setName("owner's new name");
        owner.setPassword("new password");
        owner.setCurrentPassword("password");
        modifyAccount.setOwner(owner);

        when(mockAccountDao.findById(anyLong())).thenReturn(account);
        when(mockUserTokenDao.findByToken(anyString())).thenReturn(userToken);
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);

        accountService.modifyAccount(1L, modifyAccount, "admin");

        ArgumentCaptor<Account> accountArgument = ArgumentCaptor.forClass(Account.class);
        verify(mockAccountDao).update(accountArgument.capture());
        Account modifiedAccount = accountArgument.getValue();

        assertEquals("new account path", modifiedAccount.getAccountPath());
        assertTrue(modifiedAccount.isAccountPrivate());
        assertEquals(999, modifiedAccount.getRiverQuotaRemaining());
        assertEquals("email@example.com", modifiedAccount.getOwner().getEmail());
        assertEquals("owner's new name", modifiedAccount.getOwner().getName());
        assertTrue(passwordEncoder.matches("new password", modifiedAccount.getOwner().getPassword()));
    }

    @Test
    public void createUserToken() {
        User user = new User();

        accountService.createUserToken(user);

        ArgumentCaptor<UserToken> userTokenArgument = ArgumentCaptor.forClass(UserToken.class);
        verify(mockUserTokenDao).create(userTokenArgument.capture());
        User tokenUser = userTokenArgument.getValue().getUser();

        assertEquals(user, tokenUser);
    }

    @Test
    public void getClients() {
        Account account = new Account();
        account.setClients(new HashSet<Client>());
        Client client = new Client();
        client.setId(1L);
        client.setClientId("trusted-client");
        client.setClientSecret("8b22f281afd911c3dfc59270af43db1995d5968a3447c780ba3e152e603fd9a0");
        client.setDescription("the description");
        client.setHomepage("the homepage");
        client.setRedirectUri("the redirect uri");
        account.getClients().add(client);

        when(mockAccountDao.findById(anyLong())).thenReturn(account);
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);

        accountService.setMapper(mapper);
        List<GetClientDTO> clients = accountService.getClients(1L, "username");

        assertEquals(1, clients.size());

        GetClientDTO dto = clients.get(0);
        assertEquals(1, dto.getId());
        assertEquals("trusted-client", dto.getClientId());
        assertEquals("somesecret", dto.getClientSecret());
        assertEquals("the description", dto.getDescription());
        assertEquals("the homepage", dto.getHomepage());
        assertEquals("the redirect uri", dto.getRedirectUri());
    }

    @Test
    public void createClient() {
        Account account = new Account();
        Role role = new Role();
        CreateClientDTO createClientDTO = new CreateClientDTO();
        createClientDTO.setName("new app's name");
        createClientDTO.setDescription("new app's description");
        createClientDTO.setHomepage("http://example.com");
        createClientDTO.setRedirectUri("http://example.com/redirect");

        when(mockAccountDao.findById(anyLong())).thenReturn(account);
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);
        when(mockRoleDao.findByName(anyString())).thenReturn(role);

        accountService.setMapper(mapper);
        GetClientDTO getClientDTO = accountService.createClient(1L, createClientDTO, "admin");

        ArgumentCaptor<Client> argument = ArgumentCaptor.forClass(Client.class);
        verify(mockClientDao).create(argument.capture());
        Client client = argument.getValue();
        assertEquals("new app's name", client.getName());
        assertEquals("new app's description", client.getDescription());
        assertEquals("http://example.com", client.getHomepage());
        assertEquals("http://example.com/redirect", client.getRedirectUri());
        assertTrue(client.getActive());
        assertTrue(client.getRoles().contains(role));
        assertNotNull(client.getClientId());
        assertNotNull(client.getClientSecret());

        TextEncryptor encryptor = Encryptors.text(TextUtil.convertStringToHex(accountService.getEncryptionKey()),
                TextUtil.convertStringToHex(client.getClientId()));
        assertEquals(getClientDTO.getClientSecret(), encryptor.decrypt(client.getClientSecret()));
    }

    @Test
    public void deleteClient() {
        Account account = new Account();
        Client client = new Client();

        when(mockAccountDao.findById(anyLong())).thenReturn(account);
        when(mockAccountDao.findByUsernameOrEmail(anyString())).thenReturn(account);
        when(mockClientDao.findById(anyLong())).thenReturn(client);

        accountService.deleteApp(1L, 1L, "admin");

        verify(mockClientDao).delete(client);
    }

    @Test
    public void getActivities() {
        accountService.setMapper(mapper);

        List<Activity> activities = new ArrayList<Activity>();

        // The authenticated account
        Account account = new Account();

        // Add a river activity the authenticated user owns
        Activity activity = new RiverActivity();
        activity.setId(1L);
        River river = new River();
        river.setAccount(account);
        river.setRiverPublic(true);
        ((RiverActivity) activity).setActionOnObj(river);
        activities.add(activity);

        // Add a river activity the authenticated user *does not* own
        activity = new RiverActivity();
        activity.setId(2L);
        river = new River();
        river.setAccount(account);
        river.setRiverPublic(false);
        ((RiverActivity) activity).setActionOnObj(river);
        activities.add(activity);

        // Add a bucket activity the authenticated user owns
        activity = new BucketActivity();
        activity.setId(3L);
        Bucket bucket = new Bucket();
        bucket.setAccount(account);
        bucket.setPublished(true);
        ((BucketActivity) activity).setActionOnObj(bucket);
        activities.add(activity);

        // Add a bucket activity the authenticated user *does not* own
        activity = new BucketActivity();
        activity.setId(4L);
        bucket = new Bucket();
        bucket.setAccount(account);
        bucket.setPublished(false);
        ((BucketActivity) activity).setActionOnObj(bucket);
        activities.add(activity);

        // Add a form activity the authenticated user owns
        activity = new FormActivity();
        activity.setId(5L);
        Form form = new Form();
        form.setAccount(account);
        ((FormActivity) activity).setActionOnObj(form);
        activities.add(activity);

        when(mockActivityDao.find(1L, 2, 3L, true, null)).thenReturn(activities);

        List<GetActivityDTO> ret = accountService.getActivities(1L, 2, 3L, true, null, account);
        assertEquals(3, ret.size());
        assertEquals("1", ret.get(0).getId());
        assertEquals("3", ret.get(1).getId());
        assertEquals("5", ret.get(2).getId());
    }

    /**
     * Check that getActivities will continue searching for results when all
     * activities are removed due to the permissions check.
     */
    @Test(expected = NotFoundException.class)
    public void getActivitiesRecursively() {
        accountService.setMapper(mapper);

        List<Activity> activities = new ArrayList<Activity>();

        // The authenticated account
        Account account = new Account();

        // Add a river activity the authenticated user *does not* own
        Activity activity = new RiverActivity();
        activity.setId(2L);
        River river = new River();
        river.setAccount(account);
        river.setRiverPublic(false);
        ((RiverActivity) activity).setActionOnObj(river);
        activities.add(activity);

        when(mockActivityDao.find(1L, 2, 1L, true, null)).thenReturn(activities);
        when(mockActivityDao.find(1L, 2, 2L, true, null)).thenReturn(null);

        accountService.getActivities(1L, 2, 1L, true, null, account);

    }

    @Test
    public void logRiverActivity() {
        Account account = new Account();
        River river = new River();

        accountService.logActivity(account, ActivityType.CREATE, river);

        ArgumentCaptor<Activity> argument = ArgumentCaptor.forClass(Activity.class);
        verify(mockActivityDao).create(argument.capture());
        Activity activity = argument.getValue();

        assertTrue(activity instanceof RiverActivity);
        assertEquals(river, ((RiverActivity) activity).getActionOnObj());
        assertEquals(account, activity.getAccount());
    }

    @Test
    public void logBucketActivity() {
        Account account = new Account();
        Bucket bucket = new Bucket();

        accountService.logActivity(account, ActivityType.CREATE, bucket);

        ArgumentCaptor<Activity> argument = ArgumentCaptor.forClass(Activity.class);
        verify(mockActivityDao).create(argument.capture());
        Activity activity = argument.getValue();

        assertTrue(activity instanceof BucketActivity);
        assertEquals(bucket, ((BucketActivity) activity).getActionOnObj());
        assertEquals(account, activity.getAccount());
    }

    @Test
    public void logFormActivity() {
        Account account = new Account();
        Form form = new Form();

        accountService.logActivity(account, ActivityType.CREATE, form);

        ArgumentCaptor<Activity> argument = ArgumentCaptor.forClass(Activity.class);
        verify(mockActivityDao).create(argument.capture());
        Activity activity = argument.getValue();

        assertTrue(activity instanceof FormActivity);
        assertEquals(form, ((FormActivity) activity).getActionOnObj());
        assertEquals(account, activity.getAccount());
    }

    @Test
    public void logActivityCheckActionOn() {
        Account account = new Account();
        River river = new River();

        accountService.logActivity(account, ActivityType.CREATE, river);
        accountService.logActivity(account, ActivityType.FOLLOW, river);
        accountService.logActivity(account, ActivityType.INVITE, river);
        accountService.logActivity(account, ActivityType.COMMENT, river);

        ArgumentCaptor<Activity> argument = ArgumentCaptor.forClass(Activity.class);
        verify(mockActivityDao, times(4)).create(argument.capture());

        List<Activity> activities = argument.getAllValues();
        assertEquals("create", activities.get(0).getAction());
        assertEquals("follow", activities.get(1).getAction());
        assertEquals("invite", activities.get(2).getAction());
        assertEquals("comment", activities.get(3).getAction());

    }

    @Test(expected = RuntimeException.class)
    public void logActivityOnUnknownObject() {
        Account account = new Account();

        accountService.logActivity(account, ActivityType.CREATE, new Object());
    }

    @Test
    public void addFollower() {
        AccountService spy = spy(accountService);

        Account account = new Account();
        Account follower = new Account();

        when(mockAccountDao.findById(1L)).thenReturn(account);
        when(mockAccountDao.findById(2L)).thenReturn(follower);

        spy.addFollower(1L, 2L);

        verify(mockAccountDao).addFollower(account, follower);
        verify(spy).logActivity(follower, ActivityType.FOLLOW, account);
    }

    @Test
    public void forgotPassword_Default() {
        String email = "me@example.com";
        String fullName = "Example user";
        Account mockAccount = mock(Account.class);
        User mockUser = mock(User.class);

        when(mockAccountDao.findByEmail(anyString())).thenReturn(mockAccount);
        when(mockAccount.getOwner()).thenReturn(mockUser);
        when(mockUser.getName()).thenReturn(fullName);

        accountService.forgotPassword(email);

        ArgumentCaptor<UserToken> tokenArgument = ArgumentCaptor.forClass(UserToken.class);

        verify(mockEmailHelper).sendPasswordResetEmail(eq(mockUser), tokenArgument.capture());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void forgotPassword_CrowdmapID() {
        accountService.setAuthenticationScheme(AuthenticationScheme.CROWDMAPID);

        String email = "me@example.com";
        String mailBody = "Dear user, click http://swiftriver.dev/reset_password?token=%token% to reset your password";

        Account mockAccount = mock(Account.class);
        User mockUser = mock(User.class);

        when(mockAccountDao.findByEmail(anyString())).thenReturn(mockAccount);
        when(mockAccount.getOwner()).thenReturn(mockUser);
        when(mockEmailHelper.getEmailBody(any(EmailType.class), any(Map.class), anyString())).thenReturn(mailBody);
        accountService.forgotPassword(email);

        verify(mockCrowdmapIDClient).requestPassword(email, mailBody);
    }
}