Java tutorial
/* 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); } }