com.neocotic.bloggaer.account.dao.ofy.RoleDAOImplTest.java Source code

Java tutorial

Introduction

Here is the source code for com.neocotic.bloggaer.account.dao.ofy.RoleDAOImplTest.java

Source

/* Copyright (C) 2012 Alasdair Mercer, http://neocotic.com/
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.neocotic.bloggaer.account.dao.ofy;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.time.DateUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.neocotic.bloggaer.account.Account;
import com.neocotic.bloggaer.account.Role;

/**
 * Tests for the {@link RoleDAOImpl} {@code class}.
 * 
 * @author Alasdair Mercer
 */
public class RoleDAOImplTest {

    static {
        ObjectifyService.register(Account.class);
        ObjectifyService.register(Role.class);
    }

    /** The {@link LocalServiceTestHelper} instance for testing local App Engine services. */
    private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

    /** The subject being tested. */
    private RoleDAOImpl impl;

    /** The {@link Objectify} instance for testing. */
    private Objectify ofy;

    /**
     * Creates a new instance of {@link RoleDAOImpl} and sets up {@link #helper} for each {@link Test}.
     */
    @Before
    public void before() {
        helper.setUp();
        ofy = ObjectifyService.begin();
        impl = new RoleDAOImpl();
    }

    /**
     * Cleans up after each {@link Test}.
     */
    @After
    public void after() {
        impl = null;
        ofy = null;
        helper.tearDown();
    }

    /**
     * Helper method that creates a new {@link Account} based on the information provided.
     * 
     * @param email
     *            the email address to be used
     * @param name
     *            the name to be used
     * @param enabled
     *            {@link Boolean#TRUE} if the {@code Account} should be enabled; {@link Boolean#FALSE} otherwise
     * @return The newly created {@code Account}.
     */
    private Account createAccount(String email, String name, Boolean enabled) {
        Account account = new Account();
        account.setEmail(email);
        account.setEnabled(enabled);
        account.setName(name);
        return account;
    }

    /**
     * Helper method that creates a new {@link Role} based on the information provided.
     * 
     * @param name
     *            the unique name to be used
     * @param title
     *            the title to be used
     * @return The newly created {@code Role}.
     */
    private Role createRole(String name, String title) {
        Role role = new Role();
        role.setName(name);
        role.setTitle(title);
        return role;
    }

    /**
     * Tests {@link RoleDAOImpl#count()} can return the total number of existing {@link Role Roles}.
     */
    @Test
    public void count() {
        // Ensures no Roles with these names already exist.
        String[] names = { "foo", "bar", "fu", "baz" };
        for (String name : names)
            assertNull(ofy.find(Key.create(Role.class, name)));

        // Creates Roles with the names to be counted later.
        List<Role> roles = new ArrayList<Role>();
        for (String name : names)
            roles.add(createRole(name, "Name " + roles.size()));
        Set<Key<Role>> keys = ofy.put(roles).keySet();
        assertNotNull(keys);
        assertEquals(names.length, keys.size());
        for (String name : names)
            assertTrue(keys.contains(Key.create(Role.class, name)));

        // Tests all Roles in the datastore are counted.
        assertEquals(roles.size(), impl.count());

        // Tests no Roles are in the datastore after deleting all of them.
        ofy.delete(keys);
        assertEquals(0, impl.count());
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(Role, Role)} can delete a {@link Role} while ensuring all {@link Account}
     * associations are removed correctly.
     */
    @Test
    public void deleteRoleWithRole() {
        // Ensures no Role with this name already exists.
        String name = "foo_bar";
        assertNull(ofy.find(Key.create(Role.class, name)));

        // Creates a Role to be deleted later.
        Role role1 = createRole(name, "Foo Bar");
        Key<Role> key = ofy.put(role1);
        assertNotNull(key);
        assertEquals(Key.create(Role.class, name), key);

        // Ensures key now exists in the datastore.
        Role role2 = ofy.find(key);
        assertNotNull(role2);
        assertEquals(role1, role2);

        // Tests Role has been deleted from the datastore.
        impl.deleteRole(role1, null);
        role2 = ofy.find(key);
        assertNull(role2);

        // Tests nothing happens when attempting to delete a non-existent Role from the datastore.
        impl.deleteRole(role1, null);
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(Role, Role)} throws a {@link NullPointerException} if the first {@link Role}
     * parameter is {@code null}.
     */
    @Test(expected = NullPointerException.class)
    public void deleteRoleWithRoleThrowsIfNull() {
        impl.deleteRole((Role) null, null);
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(Role, Role)} can delete a {@link Role} while ensuring associated
     * {@link Account Accounts} are updated correctly.
     */
    @Test
    public void deleteRoleWithRoleAndReplacement() {
        // TODO: Complete unit test (incl. case where replacement doesn't exist)
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(String, String)} can delete a {@link Role} identified by a name while
     * ensuring all {@link Account} associations are removed while handling missing {@code Roles} correctly.
     */
    @Test
    public void deleteRoleWithString() {
        // Ensures no Role with this name already exists.
        String name = "foo_bar";
        assertNull(ofy.find(Key.create(Role.class, name)));

        // Creates an Role with the name to be deleted later.
        Role role1 = createRole(name, "Foo Bar");
        Key<Role> key = ofy.put(role1);
        assertNotNull(key);
        assertEquals(Key.create(Role.class, name), key);

        // Ensures key now exists in the datastore.
        Role role2 = ofy.find(key);
        assertNotNull(role2);
        assertEquals(role1, role2);

        // Tests Role with the name has been deleted from the datastore.
        impl.deleteRole(name, null);
        role1 = ofy.find(key);
        assertNull(role1);

        // Tests nothing happens when attempting to delete a non-existent Role from the datastore.
        impl.deleteRole(name, null);
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(String, String)} throws an {@link IllegalArgumentException} if the first
     * {@link String} parameter is {@code null}.
     */
    @Test(expected = IllegalArgumentException.class)
    public void deleteRoleWithStringThrowsIfNull() {
        impl.deleteRole((String) null, null);
    }

    /**
     * Tests {@link RoleDAOImpl#deleteRole(Role, Role)} can delete a {@link Role} identified by a name while ensuring
     * associated {@link Account Accounts} are updated while handling missing {@code Roles} correctly.
     */
    @Test
    public void deleteRoleWithStringAndReplacement() {
        // TODO: Complete unit test (incl. case where replacement doesn't exist)
    }

    /**
     * Tests {@link RoleDAOImpl#exists(String)} can correctly determine the existence of a {@link Role} with any given
     * name.
     */
    @Test
    public void exists() {
        // Tests no Role with this name already exists.
        String name = "foo_bar";
        assertFalse(impl.exists(name));

        // Creates a Role with the name to be checked later.
        Role role = createRole(name, "Foo Bar");
        Key<Role> key = ofy.put(role);
        assertNotNull(key);
        assertEquals(Key.create(Role.class, name), key);

        // Tests a Role is found.
        assertTrue(impl.exists(name));

        // Tests no Role is found when we know it's been deleted from the datastore.
        ofy.delete(Role.class, name);
        assertFalse(impl.exists(name));
    }

    /**
     * Tests {@link RoleDAOImpl#exists(String)} throws a {@link NullPointerException} if the {@link String} parameter is
     * {@code null}.
     */
    @Test(expected = NullPointerException.class)
    public void existsThrowsIfNull() {
        impl.exists(null);
    }

    /**
     * Tests {@link RoleDAOImpl#getAccounts(Role)} can retrieve existing {@link Account Accounts} for any given
     * {@link Role} while handling the optional parameter and sorting correctly.
     */
    @Test
    public void getAccountsWithRole() {
        // Ensures no Roles with these names already exist.
        String[] names = { "foo_bar", "fu_baz", "bar_foo" };
        for (String name : names)
            assertNull(ofy.find(Key.create(Role.class, name)));

        // Create Roles with the names to be used later.
        List<Role> roles = new ArrayList<Role>();
        for (String name : names)
            roles.add(createRole(name, "Name " + roles.size()));
        Set<Key<Role>> roleKeys = ofy.put(roles).keySet();
        assertNotNull(roleKeys);
        for (String name : names)
            assertTrue(roleKeys.contains(Key.create(Role.class, name)));

        // Ensures no Accounts with these email addresses already exist.
        String[] emails = { "foo@bar.com", "fu@baz.com", "bar@foo.com", "baz@fu.com" };
        for (String email : emails)
            assertNull(ofy.find(Key.create(Account.class, email)));

        /*
         * Creates Accounts with the email addresses to be retrieved later.
         * 
         * The first Account won't be be associated with any Role, the last Account will be associated with the second
         * Role, and the other Accounts will be associated with the first Role.
         * 
         * dateCreated fields will be 1 year apart and List is reversed.
         */
        Date dateCreated = new Date();
        List<Account> accounts1 = new ArrayList<Account>();
        for (String email : emails) {
            int size = accounts1.size();
            Account account = createAccount(email, "Name " + size, Boolean.TRUE);
            if (size == emails.length - 1) {
                account.setRole(roles.get(1));
            } else if (size > 0) {
                account.setRole(roles.get(0));
            }
            dateCreated = DateUtils.addYears(dateCreated, 1);
            account.setDateCreated(dateCreated);
            accounts1.add(account);
        }
        Collections.reverse(accounts1);
        Set<Key<Account>> accountKeys = ofy.put(accounts1).keySet();
        assertNotNull(accountKeys);
        assertEquals(emails.length, accountKeys.size());
        for (String email : emails)
            assertTrue(accountKeys.contains(Key.create(Account.class, email)));

        // Reverses the List again so it's back to normal for testing sort order.
        Collections.reverse(accounts1);

        // Tests associated Accounts are retrieved from the datastore when providing the first Role.
        List<Account> accounts2 = impl.getAccounts(roles.get(0));
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(1, accounts1.size() - 1).toArray(), accounts2.toArray());

        // Tests associated Accounts are retrieved from the datastore when providing the second Role.
        accounts2 = impl.getAccounts(roles.get(1));
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(accounts1.size() - 1, accounts1.size()).toArray(), accounts2.toArray());

        // Tests no Accounts are retrieved from the datastore when providing a known unlinked Role.
        accounts2 = impl.getAccounts(roles.get(2));
        assertNotNull(accounts2);
        assertEquals(0, accounts2.size());

        // Tests an unlinked Account is retrieved from the datastore when providing no Role.
        accounts2 = impl.getAccounts((Role) null);
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(0, 1).toArray(), accounts2.toArray());
    }

    /**
     * Tests {@link RoleDAOImpl#getAccounts(String)} can retrieve existing {@link Account Accounts} for any given
     * {@link Role} name while handling the optional parameter, missing {@code Roles} and sorting correctly.
     */
    @Test
    public void getAccountsWithString() {
        // Ensures no Roles with these names already exist.
        String[] names = { "foo_bar", "fu_baz", "bar_foo" };
        for (String name : names)
            assertNull(ofy.find(Key.create(Role.class, name)));

        // Create Roles with the names to be used later.
        List<Role> roles = new ArrayList<Role>();
        for (String name : names)
            roles.add(createRole(name, "Name " + roles.size()));
        Set<Key<Role>> roleKeys = ofy.put(roles).keySet();
        assertNotNull(roleKeys);
        for (String name : names)
            assertTrue(roleKeys.contains(Key.create(Role.class, name)));

        // Ensures no Accounts with these email addresses already exist.
        String[] emails = { "foo@bar.com", "fu@baz.com", "bar@foo.com", "baz@fu.com" };
        for (String email : emails)
            assertNull(ofy.find(Key.create(Account.class, email)));

        /*
         * Creates Accounts with the email addresses to be retrieved later.
         * 
         * The first Account won't be be associated with any Role, the last Account will be associated with the second
         * Role, and the other Accounts will be associated with the first Role.
         * 
         * dateCreated fields will be 1 year apart and List is reversed.
         */
        Date dateCreated = new Date();
        List<Account> accounts1 = new ArrayList<Account>();
        for (String email : emails) {
            int size = accounts1.size();
            Account account = createAccount(email, "Name " + size, Boolean.TRUE);
            if (size == emails.length - 1) {
                account.setRole(roles.get(1));
            } else if (size > 0) {
                account.setRole(roles.get(0));
            }
            dateCreated = DateUtils.addYears(dateCreated, 1);
            account.setDateCreated(dateCreated);
            accounts1.add(account);
        }
        Collections.reverse(accounts1);
        Set<Key<Account>> accountKeys = ofy.put(accounts1).keySet();
        assertNotNull(accountKeys);
        assertEquals(emails.length, accountKeys.size());
        for (String email : emails)
            assertTrue(accountKeys.contains(Key.create(Account.class, email)));

        // Reverses the List again so it's back to normal for testing sort order.
        Collections.reverse(accounts1);

        // Tests associated Accounts are retrieved from the datastore when providing the first name.
        List<Account> accounts2 = impl.getAccounts(names[0]);
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(1, accounts1.size() - 1).toArray(), accounts2.toArray());

        // Tests associated Accounts are retrieved from the datastore when providing the second name.
        accounts2 = impl.getAccounts(names[1]);
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(accounts1.size() - 1, accounts1.size()).toArray(), accounts2.toArray());

        // Tests no Accounts are retrieved from the datastore when providing a known unlinked named Role.
        accounts2 = impl.getAccounts(names[2]);
        assertNotNull(accounts2);
        assertEquals(0, accounts2.size());

        // Tests an unlinked Account is retrieved from the datastore when providing no name.
        accounts2 = impl.getAccounts((String) null);
        assertNotNull(accounts2);
        assertArrayEquals(accounts1.subList(0, 1).toArray(), accounts2.toArray());

        // Tests no Accounts are retrieved from the datastore when providing an invalid name.
        accounts2 = impl.getAccounts("baz_fu");
        assertNotNull(accounts2);
        assertEquals(0, accounts2.size());
    }

    /**
     * Tests {@link RoleDAOImpl#getRole(String)} can return an existing {@link Role} while handling missing
     * {@code Roles} correctly.
     */
    @Test
    public void getRole() {
        // Ensures no Role with this name already exists.
        String name = "foo_bar";
        assertNull(ofy.find(Key.create(Role.class, name)));

        // Creates an Role with the name to be retrieved later.
        Role role1 = createRole(name, "Foo Bar");
        Key<Role> key = ofy.put(role1);
        assertNotNull(key);
        assertEquals(Key.create(Role.class, name), key);

        // Tests a Role is retrieved from the datastore when providing a matching name.
        Role role2 = impl.getRole(name);
        assertNotNull(role2);
        assertEquals(role1, role2);

        // Tests nothing is retrieved from the datastore when providing an invalid name.
        role2 = impl.getRole("fu_baz");
        assertNull(role2);

        // Tests nothing is retrieved from the datastore after deleting the known object.
        ofy.delete(Role.class, name);
        role2 = impl.getRole(name);
        assertNull(role2);
    }

    /**
     * Tests {@link RoleDAOImpl#getRole(String)} throws an {@link IllegalArgumentException} if the {@link String}
     * parameter is {@code null}.
     */
    @Test(expected = IllegalArgumentException.class)
    public void getRoleThrowsIfNull() {
        impl.getRole(null);
    }

    /**
     * Tests {@link RoleDAOImpl#getRoles()} can return existing {@link Role Roles} while handling sorting correctly.
     */
    @Test
    public void getRoles() {
        // Ensures no Roles with these names already exist.
        String[] names = { "foo_bar", "fu_baz", "bar_foo", "baz_fu" };
        for (String name : names)
            assertNull(ofy.find(Key.create(Role.class, name)));

        // Creates Roles with the names to be retrieved later.
        List<Role> roles1 = new ArrayList<Role>();
        for (String name : names)
            roles1.add(createRole(name, "Name " + roles1.size()));
        // Reverses the List to ensure sort order can be tested.
        Collections.reverse(roles1);
        Set<Key<Role>> keys = ofy.put(roles1).keySet();
        assertNotNull(keys);
        assertEquals(names.length, keys.size());
        for (String name : names)
            assertTrue(keys.contains(Key.create(Role.class, name)));

        // Reverses the List again so it's back to normal for testing sort order.
        Collections.reverse(roles1);

        // Tests all Roles are retrieved from the datastore.
        List<Role> roles2 = impl.getRoles();
        assertNotNull(roles2);
        assertArrayEquals(roles1.toArray(), roles2.toArray());

        // Tests no Roles are retrieved from the datastore after deleting all of them.
        ofy.delete(keys);
        roles2 = impl.getRoles();
        assertNotNull(roles2);
        assertEquals(0, roles2.size());
    }

    /**
     * Tests {@link RoleDAOImpl#updateRole(Role)} can create a new {@link Role} and update an existing one.
     */
    @Test
    public void updateRole() {
        // Ensures no Role with this name already exists.
        String name = "foo_bar";
        assertNull(ofy.find(Key.create(Role.class, name)));

        // Tests Role is created in the datastore and local instance is updated.
        Role role1 = createRole(name, "Foo Bar");
        Role role2 = impl.updateRole(role1);
        assertNotNull(role2);
        assertSame(role1, role2);

        // Tests local instance equals that found in the datastore.
        role2 = ofy.find(Key.create(Role.class, name));
        assertNotNull(role2);
        assertEquals(role1, role2);

        // Tests Role is updated in the datastore and local instance is updated.
        role1.setTitle("Fu Baz");
        role2 = impl.updateRole(role1);
        assertNotNull(role2);
        assertEquals(role1, role2);
    }

    /**
     * Tests {@link RoleDAOImpl#updateRole(Role)} throws a {@link NullPointerException} if the {@link Role} parameter is
     * {@code null}.
     */
    @Test(expected = NullPointerException.class)
    public void updateRoleThrowsIfNull() {
        impl.updateRole(null);
    }

    /**
     * Tests {@link RoleDAOImpl#updateRoles(List)} can create new {@link Role Roles} and update existing ones.
     */
    @Test
    public void updateRoles() {
        // Ensures no Roles with these names already exist.
        String[] names = { "foo_bar", "fu_baz" };
        for (String name : names)
            assertNull(ofy.find(Key.create(Role.class, name)));

        // Tests Roles are created in the datastore and local instance are updated.
        List<Role> roles1 = new ArrayList<Role>();
        for (String name : names)
            roles1.add(createRole(name, "Name " + roles1.size()));
        List<Role> roles2 = impl.updateRoles(roles1);
        assertNotNull(roles2);
        assertArrayEquals(roles1.toArray(), roles2.toArray());

        // Tests local instances equals those found in the datastore.
        roles2 = ofy.query(Role.class).list();
        assertNotNull(roles2);
        assertArrayEquals(roles1.toArray(), roles2.toArray());

        // Tests Roles are updated in the datastore and local instances are updated.
        for (Role role : roles1)
            role.setTitle("Changed " + role.getTitle());
        roles2 = impl.updateRoles(roles1);
        assertNotNull(roles2);
        assertArrayEquals(roles1.toArray(), roles2.toArray());
    }

    /**
     * Tests {@link RoleDAOImpl#updateRoles(List)} throws a {@link NullPointerException} if the {@link List} parameter
     * is {@code null}.
     */
    @Test(expected = NullPointerException.class)
    public void updateRolesThrowsIfNull() {
        impl.updateRoles(null);
    }
}