/* ===================================================================
* AbstractSpringEnabledTest.java
*
* Copyright (c) 2004 Matt Magoffin. Created Sep 9, 2004 10:07:47 AM.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ===================================================================
* $Id: AbstractSpringEnabledTest.java 74 2009-05-15 04:44:37Z msqr $
* ===================================================================
*/
package magoffin.matt.ieat.test;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import junit.framework.TestCase;
import magoffin.matt.ieat.biz.BizContext;
import magoffin.matt.ieat.biz.DomainObjectFactory;
import magoffin.matt.ieat.biz.RecipeBiz;
import magoffin.matt.ieat.biz.RecipeSearchBiz;
import magoffin.matt.ieat.biz.RecipeSearchIndexBiz;
import magoffin.matt.ieat.biz.UserBiz;
import magoffin.matt.ieat.dao.BaseDao;
import magoffin.matt.ieat.dao.CourseDao;
import magoffin.matt.ieat.dao.DifficultyDao;
import magoffin.matt.ieat.dao.EthnicityDao;
import magoffin.matt.ieat.dao.IngredientDao;
import magoffin.matt.ieat.dao.MealDao;
import magoffin.matt.ieat.dao.PrepTimeDao;
import magoffin.matt.ieat.dao.RecipeDao;
import magoffin.matt.ieat.dao.UnitDao;
import magoffin.matt.ieat.dao.UserDao;
import magoffin.matt.ieat.domain.Base;
import magoffin.matt.ieat.domain.Course;
import magoffin.matt.ieat.domain.Difficulty;
import magoffin.matt.ieat.domain.Ethnicity;
import magoffin.matt.ieat.domain.Ingredient;
import magoffin.matt.ieat.domain.PrepTime;
import magoffin.matt.ieat.domain.Recipe;
import magoffin.matt.ieat.domain.RecipeIngredient;
import magoffin.matt.ieat.domain.RecipeStep;
import magoffin.matt.ieat.domain.System;
import magoffin.matt.ieat.domain.Unit;
import magoffin.matt.ieat.domain.User;
import magoffin.matt.xweb.util.AppContextSupport;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* Base JUnit test case for Spring related test cases.
*
*
Code derived from Robert Newson's posts on
* http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=146&showComments=true#comments
*
*
* @author Matt Magoffin (spamsqr@msqr.us)
* @version $Revision: 74 $ $Date: 2009-05-15 16:44:37 +1200 (Fri, 15 May 2009) $
*/
public abstract class AbstractSpringEnabledTest extends TestCase {
/** A class logger. */
protected final Logger log = Logger.getLogger(getClass());
/** The test user login. */
public static final String TEST_USER_LOGIN = "_test_";
/** The test user password. */
public static final String TEST_USER_PASS = "_foo_";
/** The default load ID. */
public static final Integer DEFAULT_LOAD_ID = new Integer(1);
private static Logger LOG = Logger.getLogger(AbstractSpringEnabledTest.class);
private static Map applicationContextCache
= new HashMap();
private static final String[] DEFAULT_APP_CONTEXT_PATHS = {
//"classpath:magoffin/matt/ieat/test/AbstractSpringEnabledTestContext.xml",
"web/WEB-INF/applicationContext.xml"
};
private AbstractApplicationContext context;
/**
* Constructor.
*/
public AbstractSpringEnabledTest() {
super();
}
/**
* Construct with a name.
* @param name the name
*/
public AbstractSpringEnabledTest(String name) {
super(name);
}
/**
* Get a test BizContext.
* @return the biz context
*/
protected BizContext getBizContext() {
AppContextSupport appContextSupport = getAppContextSupport();
return new TestBizContext(appContextSupport,getDummyUser());
}
/**
* Get the domain object factory.
* @return the domain object factory
*/
protected DomainObjectFactory getDomainObjectFactory() {
return (DomainObjectFactory)getContext().getBean("domainObjectFactory");
}
/**
* Get the application context.
* @return the context
*/
protected ApplicationContext getContext() {
assertNotNull(context);
return context;
}
/**
* Get a test property from the test resource bundle.
* @param key the key
* @return the property value
*/
protected String getTestProperty(String key) {
ResourceBundle rsrc = ResourceBundle.getBundle("test.properties");
return rsrc.getString(key);
}
/**
* Get a list of file paths to add as Spring contexts.
*
* Extending test cases can override this method to provide
* a different default set (or null for none).
* @return the contexts
*/
protected String[] getDefaultContexts() {
return DEFAULT_APP_CONTEXT_PATHS;
}
@Override
protected void setUp() throws Exception {
super.setUp();
context = null;
List> classHierarchy = getClassHierarchy();
for (int i = classHierarchy.size() - 1; i >= 0; i--) {
Class> clazz = classHierarchy.get(i);
context = getApplicationContext(clazz,
getClassName(clazz) + "Context.xml", context);
}
if ( getDefaultContexts() != null && getDefaultContexts().length > 0 ) {
context = new FileSystemXmlApplicationContext(getDefaultContexts(),context);
}
}
@Override
protected void tearDown() throws Exception {
closeContext();
}
/**
* Close the context.
*/
protected final void closeContext() {
if (context != null) {
context.close();
context = null;
}
}
private List> getClassHierarchy() {
List> result = new ArrayList>();
Class> superclass = getClass();
do {
result.add(superclass);
} while ((superclass = superclass.getSuperclass()) != null);
return result;
}
private String getClassName(Class> clazz) {
String fullClassName = clazz.getName();
String result = fullClassName
.substring(fullClassName.lastIndexOf(".") + 1);
return result;
}
private AbstractApplicationContext getApplicationContext(Class> clazz,
String resourceName, AbstractApplicationContext parentContext) {
/*if ( clazz == AbstractSpringEnabledTest.class ) {
return null; // don't load this class or any parent class
}*/
log.debug("Attempting to locate " + resourceName);
URL url = clazz.getResource(resourceName);
if (url == null) {
return parentContext;
}
if (!applicationContextCache.containsKey(url)) {
log.info("Loading " + url);
applicationContextCache.put(url,
new ClassPathXmlApplicationContext(new String[] { url
.toString() }, parentContext));
}
return applicationContextCache.get(url);
}
/**
* Delete a recipe.
* @param r the recipe
*/
protected void cleanOutRecipe(Recipe r) {
if ( r == null || r.getRecipeId() == null ) {
return;
}
RecipeDao recipeDao = getRecipeDao();
try {
recipeDao.delete(recipeDao.get(r.getRecipeId()));
} catch ( Exception e ) {
LOG.warn("Unable to clean out recipe",e);
}
}
/**
* Delete a user.
* @param u the user to delete
*/
protected void cleanOutUser(User u) {
if ( u == null || u.getUserId() == null ) {
return;
}
UserDao userDao = getUserDao();
try {
userDao.delete(userDao.get(u.getUserId()));
} catch ( Exception e ) {
LOG.warn("Unable to clean out user",e);
}
}
/**
* Get a dummy recipe (non-persisted).
* @return recipe
*/
@SuppressWarnings("unchecked")
protected Recipe getDummyRecipe() {
DomainObjectFactory dof = getDomainObjectFactory();
Recipe r = dof.getRecipeInstance();
r.setCreatedDate(Calendar.getInstance());
r.setBase(getTestBase());
r.setCourse(getTestCourse());
r.setDifficulty(getTestDifficulty());
r.setEthnicity(getTestEthnicity());
r.setExcerpt("This is the test recipe description.");
r.setName("My Test Recipe " +r.getCreatedDate().getTime() );
r.setPrepTime(getTestPrepTime());
r.setServingSize(new Integer(1));
r.setSource("iEat Test Case");
System system = dof.getSystemInstance();
system.setSystemId(getTestSystemId());
system.setValue("US");
r.setSystem(system);
List units = getUnitDao().getUnits();
List ingredients = getIngredientDao().getIngredients();
for ( int i = 0; i < 3 && i < ingredients.size(); i++ ) {
RecipeIngredient ri = dof.getRecipeIngredientInstance();
ri.setQuantity(1.5);
ri.setIngredient((Ingredient)ingredients.get(i));
ri.setUnit((Unit)units.get(0));
r.getIngredient().add(ri);
}
for ( int i = 0; i < 3; i++ ) {
RecipeStep step = dof.getRecipeStepInstance();
step.setValue("Dummy step " +i);
r.getStep().add(step);
}
return r;
}
/**
* API for test callback with dummy user.
*/
protected static interface TestWithDummyUser {
/**
* Perform the test.
* @param user the dummy user to test with
* @throws Exception if any error occurs
*/
public void test(User user) throws Exception;
}
/**
* Run a test with a registered dummy user.
* @param callback the callback test
* @throws Exception if any error occurs
*/
protected void doTestWithRegisteredDummyUser(TestWithDummyUser callback) throws Exception {
User u = null;
UserBiz userBiz = getUserBiz();
try {
u = getDummyUser();
u = userBiz.storeUser(u,null);
callback.test(u);
} finally {
if ( u != null && u.getUserId() != null ) {
userBiz.removeUser(u.getUserId(),null);
}
}
}
/**
* API for a test with a persisted recipe.
*/
protected static interface TestWithRecipe {
/**
* Run the test.
* @param recipe the persisted recipe
* @param context the test context
* @throws Exception if an error occurs
*/
public void test(Recipe recipe, BizContext context) throws Exception;
}
/**
* Run a test with a persisted recipe.
* @param callback the callback
* @throws Exception if an error occurs
*/
protected void doTestWithRecipe(final TestWithRecipe callback) throws Exception {
doTestWithRegisteredDummyUser(new TestWithDummyUser() {
public void test(User user) throws Exception {
Recipe r = null;
RecipeBiz recipeBiz = getRecipeBiz();
BizContext bizContext = new TestBizContext(getAppContextSupport(),user);
try {
r = getDummyRecipe();
r = recipeBiz.storeRecipe(r,bizContext);
callback.test(r,bizContext);
} finally {
if ( r != null && r.getRecipeId() != null ) {
recipeBiz.removeRecipe(r.getRecipeId(),bizContext);
}
}
}
});
}
/**
* @return the AppContextSupport
*/
protected AppContextSupport getAppContextSupport() {
AppContextInitializer init = (AppContextInitializer)getContext()
.getBean("applicationInitializer",AppContextInitializer.class);
return init.getAppContextSupport();
}
/**
* @return the RecipeDao
*/
protected RecipeDao getRecipeDao() {
return (RecipeDao)getContext().getBean("recipeDao");
}
/**
* @return the MealDao
*/
protected MealDao getMealDao() {
return (MealDao)getContext().getBean("mealDao");
}
/**
* @return the BaseDao
*/
protected BaseDao getBaseDao() {
return (BaseDao)getContext().getBean("baseDao");
}
/**
* @return the CourseDao
*/
protected CourseDao getCourseDao() {
return (CourseDao)getContext().getBean("courseDao");
}
/**
* @return the DifficultyDao
*/
protected DifficultyDao getDifficultyDao() {
return (DifficultyDao)getContext().getBean("difficultyDao");
}
/**
* @return the EthnicityDao
*/
protected EthnicityDao getEthnicityDao() {
return (EthnicityDao)getContext().getBean("ethnicityDao");
}
/**
* @return the IngredientDao
*/
protected IngredientDao getIngredientDao() {
return (IngredientDao)getContext().getBean("ingredientDao");
}
/**
* @return the PrepTimeDao
*/
protected PrepTimeDao getPrepTimeDao() {
return (PrepTimeDao)getContext().getBean("prepTimeDao");
}
/**
* @return the UnitDao
*/
protected UnitDao getUnitDao() {
return (UnitDao)getContext().getBean("unitDao");
}
/**
* @return a test recipe ID
*/
protected Integer getTestRecipeId() {
return getTestIdOrDefault("test.load.recipe.id",DEFAULT_LOAD_ID);
}
/**
* @return a test Base ID
*/
protected Integer getTestBaseId() {
return getTestIdOrDefault("test.load.base.id",DEFAULT_LOAD_ID);
}
/**
* @return a test Base
*/
protected Base getTestBase() {
return getBaseDao().getBases().get(0);
}
/**
* @return a test Course ID
*/
protected Integer getTestCourseId() {
return getTestIdOrDefault("test.load.course.id",DEFAULT_LOAD_ID);
}
/**
* @return a test Difficulty
*/
protected Difficulty getTestDifficulty() {
return getDifficultyDao().getDifficulties().get(0);
}
/**
* @return a test Difficulty ID
*/
protected Integer getTestDifficultyId() {
return getTestIdOrDefault("test.load.difficulty.id",DEFAULT_LOAD_ID);
}
/**
* @return a test Ethnicity
*/
protected Ethnicity getTestEthnicity() {
return getEthnicityDao().getEthnicities().get(0);
}
/**
* @return a test Ehtnicity ID
*/
protected Integer getTestEthnicityId() {
return getTestIdOrDefault("test.load.ethnicity.id",DEFAULT_LOAD_ID);
}
/**
* @return a test PrepTime
*/
protected PrepTime getTestPrepTime() {
return getPrepTimeDao().getPrepTimes().get(0);
}
/**
* @return a test PrepTime ID
*/
protected Integer getTestPrepTimeId() {
return getTestIdOrDefault("test.load.preptime.id",DEFAULT_LOAD_ID);
}
/**
* @return a test System ID
*/
protected Integer getTestSystemId() {
return getTestIdOrDefault("test.load.system.id",DEFAULT_LOAD_ID);
}
private Integer getTestIdOrDefault(String key, Integer defaultId) {
try {
return Integer.valueOf(getTestProperty(key));
} catch ( Exception e ) {
// nothing
}
return defaultId;
}
/**
* Get a dummy user.
* @return the dummy user.
*/
protected User getDummyUser() {
User u = getDomainObjectFactory().getUserInstance();
u.setAccessLevel(new Integer(1));
u.setCountry(Locale.getDefault().getCountry());
u.setCreatedDate(Calendar.getInstance());
u.setEmail("ieat.test@msqr.us");
u.setLanguage(Locale.getDefault().getLanguage());
u.setLogin(TEST_USER_LOGIN);
u.setName("Test User");
u.setPassword(TEST_USER_PASS);
return u;
}
/**
* @return the UserBiz
*/
protected UserBiz getUserBiz() {
return (UserBiz)getContext().getBean("userBiz");
}
/**
* @return the UserDao
*/
protected UserDao getUserDao() {
return (UserDao)getContext().getBean("userDao");
}
/**
* @return a test Course
*/
protected Course getTestCourse() {
return getCourseDao().getCourses().get(0);
}
/**
* @return the RecipeBiz
*/
protected RecipeBiz getRecipeBiz() {
return (RecipeBiz)getContext().getBean("recipeBiz");
}
/**
* @return the RecipeSearchBiz
*/
protected RecipeSearchBiz getRecipeSearchBiz() {
return (RecipeSearchBiz)getContext().getBean("recipeSearchBiz");
}
/**
* @return the RecipeSearchIndexBiz
*/
protected RecipeSearchIndexBiz getRecipeSearchIndexBiz() {
return (RecipeSearchIndexBiz)getContext().getBean("recipeSearchIndexBiz");
}
}