AbstractSpringEnabledTest.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /* ===================================================================
  2. * AbstractSpringEnabledTest.java
  3. *
  4. * Copyright (c) 2004 Matt Magoffin. Created Sep 9, 2004 10:07:47 AM.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19. * 02111-1307 USA
  20. * ===================================================================
  21. * $Id: AbstractSpringEnabledTest.java 74 2009-05-15 04:44:37Z msqr $
  22. * ===================================================================
  23. */
  24. package magoffin.matt.ieat.test;
  25. import java.net.URL;
  26. import java.util.ArrayList;
  27. import java.util.Calendar;
  28. import java.util.HashMap;
  29. import java.util.List;
  30. import java.util.Locale;
  31. import java.util.Map;
  32. import java.util.ResourceBundle;
  33. import junit.framework.TestCase;
  34. import magoffin.matt.ieat.biz.BizContext;
  35. import magoffin.matt.ieat.biz.DomainObjectFactory;
  36. import magoffin.matt.ieat.biz.RecipeBiz;
  37. import magoffin.matt.ieat.biz.RecipeSearchBiz;
  38. import magoffin.matt.ieat.biz.RecipeSearchIndexBiz;
  39. import magoffin.matt.ieat.biz.UserBiz;
  40. import magoffin.matt.ieat.dao.BaseDao;
  41. import magoffin.matt.ieat.dao.CourseDao;
  42. import magoffin.matt.ieat.dao.DifficultyDao;
  43. import magoffin.matt.ieat.dao.EthnicityDao;
  44. import magoffin.matt.ieat.dao.IngredientDao;
  45. import magoffin.matt.ieat.dao.MealDao;
  46. import magoffin.matt.ieat.dao.PrepTimeDao;
  47. import magoffin.matt.ieat.dao.RecipeDao;
  48. import magoffin.matt.ieat.dao.UnitDao;
  49. import magoffin.matt.ieat.dao.UserDao;
  50. import magoffin.matt.ieat.domain.Base;
  51. import magoffin.matt.ieat.domain.Course;
  52. import magoffin.matt.ieat.domain.Difficulty;
  53. import magoffin.matt.ieat.domain.Ethnicity;
  54. import magoffin.matt.ieat.domain.Ingredient;
  55. import magoffin.matt.ieat.domain.PrepTime;
  56. import magoffin.matt.ieat.domain.Recipe;
  57. import magoffin.matt.ieat.domain.RecipeIngredient;
  58. import magoffin.matt.ieat.domain.RecipeStep;
  59. import magoffin.matt.ieat.domain.System;
  60. import magoffin.matt.ieat.domain.Unit;
  61. import magoffin.matt.ieat.domain.User;
  62. import magoffin.matt.xweb.util.AppContextSupport;
  63. import org.apache.log4j.Logger;
  64. import org.springframework.context.ApplicationContext;
  65. import org.springframework.context.support.AbstractApplicationContext;
  66. import org.springframework.context.support.ClassPathXmlApplicationContext;
  67. import org.springframework.context.support.FileSystemXmlApplicationContext;
  68. /**
  69. * Base JUnit test case for Spring related test cases.
  70. *
  71. * <p>Code derived from Robert Newson's posts on
  72. * http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=146&showComments=true#comments
  73. * </p>
  74. *
  75. * @author Matt Magoffin (spamsqr@msqr.us)
  76. * @version $Revision: 74 $ $Date: 2009-05-15 16:44:37 +1200 (Fri, 15 May 2009) $
  77. */
  78. public abstract class AbstractSpringEnabledTest extends TestCase {
  79. /** A class logger. */
  80. protected final Logger log = Logger.getLogger(getClass());
  81. /** The test user login. */
  82. public static final String TEST_USER_LOGIN = "_test_";
  83. /** The test user password. */
  84. public static final String TEST_USER_PASS = "_foo_";
  85. /** The default load ID. */
  86. public static final Integer DEFAULT_LOAD_ID = new Integer(1);
  87. private static Logger LOG = Logger.getLogger(AbstractSpringEnabledTest.class);
  88. private static Map<URL, AbstractApplicationContext> applicationContextCache
  89. = new HashMap<URL, AbstractApplicationContext>();
  90. private static final String[] DEFAULT_APP_CONTEXT_PATHS = {
  91. //"classpath:magoffin/matt/ieat/test/AbstractSpringEnabledTestContext.xml",
  92. "web/WEB-INF/applicationContext.xml"
  93. };
  94. private AbstractApplicationContext context;
  95. /**
  96. * Constructor.
  97. */
  98. public AbstractSpringEnabledTest() {
  99. super();
  100. }
  101. /**
  102. * Construct with a name.
  103. * @param name the name
  104. */
  105. public AbstractSpringEnabledTest(String name) {
  106. super(name);
  107. }
  108. /**
  109. * Get a test BizContext.
  110. * @return the biz context
  111. */
  112. protected BizContext getBizContext() {
  113. AppContextSupport appContextSupport = getAppContextSupport();
  114. return new TestBizContext(appContextSupport,getDummyUser());
  115. }
  116. /**
  117. * Get the domain object factory.
  118. * @return the domain object factory
  119. */
  120. protected DomainObjectFactory getDomainObjectFactory() {
  121. return (DomainObjectFactory)getContext().getBean("domainObjectFactory");
  122. }
  123. /**
  124. * Get the application context.
  125. * @return the context
  126. */
  127. protected ApplicationContext getContext() {
  128. assertNotNull(context);
  129. return context;
  130. }
  131. /**
  132. * Get a test property from the test resource bundle.
  133. * @param key the key
  134. * @return the property value
  135. */
  136. protected String getTestProperty(String key) {
  137. ResourceBundle rsrc = ResourceBundle.getBundle("test.properties");
  138. return rsrc.getString(key);
  139. }
  140. /**
  141. * Get a list of file paths to add as Spring contexts.
  142. *
  143. * <p>Extending test cases can override this method to provide
  144. * a different default set (or <em>null</em> for none).</p>
  145. * @return the contexts
  146. */
  147. protected String[] getDefaultContexts() {
  148. return DEFAULT_APP_CONTEXT_PATHS;
  149. }
  150. @Override
  151. protected void setUp() throws Exception {
  152. super.setUp();
  153. context = null;
  154. List<Class<?>> classHierarchy = getClassHierarchy();
  155. for (int i = classHierarchy.size() - 1; i >= 0; i--) {
  156. Class<?> clazz = classHierarchy.get(i);
  157. context = getApplicationContext(clazz,
  158. getClassName(clazz) + "Context.xml", context);
  159. }
  160. if ( getDefaultContexts() != null && getDefaultContexts().length > 0 ) {
  161. context = new FileSystemXmlApplicationContext(getDefaultContexts(),context);
  162. }
  163. }
  164. @Override
  165. protected void tearDown() throws Exception {
  166. closeContext();
  167. }
  168. /**
  169. * Close the context.
  170. */
  171. protected final void closeContext() {
  172. if (context != null) {
  173. context.close();
  174. context = null;
  175. }
  176. }
  177. private List<Class<?>> getClassHierarchy() {
  178. List<Class<?>> result = new ArrayList<Class<?>>();
  179. Class<?> superclass = getClass();
  180. do {
  181. result.add(superclass);
  182. } while ((superclass = superclass.getSuperclass()) != null);
  183. return result;
  184. }
  185. private String getClassName(Class<?> clazz) {
  186. String fullClassName = clazz.getName();
  187. String result = fullClassName
  188. .substring(fullClassName.lastIndexOf(".") + 1);
  189. return result;
  190. }
  191. private AbstractApplicationContext getApplicationContext(Class<?> clazz,
  192. String resourceName, AbstractApplicationContext parentContext) {
  193. /*if ( clazz == AbstractSpringEnabledTest.class ) {
  194. return null; // don't load this class or any parent class
  195. }*/
  196. log.debug("Attempting to locate " + resourceName);
  197. URL url = clazz.getResource(resourceName);
  198. if (url == null) {
  199. return parentContext;
  200. }
  201. if (!applicationContextCache.containsKey(url)) {
  202. log.info("Loading " + url);
  203. applicationContextCache.put(url,
  204. new ClassPathXmlApplicationContext(new String[] { url
  205. .toString() }, parentContext));
  206. }
  207. return applicationContextCache.get(url);
  208. }
  209. /**
  210. * Delete a recipe.
  211. * @param r the recipe
  212. */
  213. protected void cleanOutRecipe(Recipe r) {
  214. if ( r == null || r.getRecipeId() == null ) {
  215. return;
  216. }
  217. RecipeDao recipeDao = getRecipeDao();
  218. try {
  219. recipeDao.delete(recipeDao.get(r.getRecipeId()));
  220. } catch ( Exception e ) {
  221. LOG.warn("Unable to clean out recipe",e);
  222. }
  223. }
  224. /**
  225. * Delete a user.
  226. * @param u the user to delete
  227. */
  228. protected void cleanOutUser(User u) {
  229. if ( u == null || u.getUserId() == null ) {
  230. return;
  231. }
  232. UserDao userDao = getUserDao();
  233. try {
  234. userDao.delete(userDao.get(u.getUserId()));
  235. } catch ( Exception e ) {
  236. LOG.warn("Unable to clean out user",e);
  237. }
  238. }
  239. /**
  240. * Get a dummy recipe (non-persisted).
  241. * @return recipe
  242. */
  243. @SuppressWarnings("unchecked")
  244. protected Recipe getDummyRecipe() {
  245. DomainObjectFactory dof = getDomainObjectFactory();
  246. Recipe r = dof.getRecipeInstance();
  247. r.setCreatedDate(Calendar.getInstance());
  248. r.setBase(getTestBase());
  249. r.setCourse(getTestCourse());
  250. r.setDifficulty(getTestDifficulty());
  251. r.setEthnicity(getTestEthnicity());
  252. r.setExcerpt("This is the test recipe description.");
  253. r.setName("My Test Recipe " +r.getCreatedDate().getTime() );
  254. r.setPrepTime(getTestPrepTime());
  255. r.setServingSize(new Integer(1));
  256. r.setSource("iEat Test Case");
  257. System system = dof.getSystemInstance();
  258. system.setSystemId(getTestSystemId());
  259. system.setValue("US");
  260. r.setSystem(system);
  261. List units = getUnitDao().getUnits();
  262. List ingredients = getIngredientDao().getIngredients();
  263. for ( int i = 0; i < 3 && i < ingredients.size(); i++ ) {
  264. RecipeIngredient ri = dof.getRecipeIngredientInstance();
  265. ri.setQuantity(1.5);
  266. ri.setIngredient((Ingredient)ingredients.get(i));
  267. ri.setUnit((Unit)units.get(0));
  268. r.getIngredient().add(ri);
  269. }
  270. for ( int i = 0; i < 3; i++ ) {
  271. RecipeStep step = dof.getRecipeStepInstance();
  272. step.setValue("Dummy step " +i);
  273. r.getStep().add(step);
  274. }
  275. return r;
  276. }
  277. /**
  278. * API for test callback with dummy user.
  279. */
  280. protected static interface TestWithDummyUser {
  281. /**
  282. * Perform the test.
  283. * @param user the dummy user to test with
  284. * @throws Exception if any error occurs
  285. */
  286. public void test(User user) throws Exception;
  287. }
  288. /**
  289. * Run a test with a registered dummy user.
  290. * @param callback the callback test
  291. * @throws Exception if any error occurs
  292. */
  293. protected void doTestWithRegisteredDummyUser(TestWithDummyUser callback) throws Exception {
  294. User u = null;
  295. UserBiz userBiz = getUserBiz();
  296. try {
  297. u = getDummyUser();
  298. u = userBiz.storeUser(u,null);
  299. callback.test(u);
  300. } finally {
  301. if ( u != null && u.getUserId() != null ) {
  302. userBiz.removeUser(u.getUserId(),null);
  303. }
  304. }
  305. }
  306. /**
  307. * API for a test with a persisted recipe.
  308. */
  309. protected static interface TestWithRecipe {
  310. /**
  311. * Run the test.
  312. * @param recipe the persisted recipe
  313. * @param context the test context
  314. * @throws Exception if an error occurs
  315. */
  316. public void test(Recipe recipe, BizContext context) throws Exception;
  317. }
  318. /**
  319. * Run a test with a persisted recipe.
  320. * @param callback the callback
  321. * @throws Exception if an error occurs
  322. */
  323. protected void doTestWithRecipe(final TestWithRecipe callback) throws Exception {
  324. doTestWithRegisteredDummyUser(new TestWithDummyUser() {
  325. public void test(User user) throws Exception {
  326. Recipe r = null;
  327. RecipeBiz recipeBiz = getRecipeBiz();
  328. BizContext bizContext = new TestBizContext(getAppContextSupport(),user);
  329. try {
  330. r = getDummyRecipe();
  331. r = recipeBiz.storeRecipe(r,bizContext);
  332. callback.test(r,bizContext);
  333. } finally {
  334. if ( r != null && r.getRecipeId() != null ) {
  335. recipeBiz.removeRecipe(r.getRecipeId(),bizContext);
  336. }
  337. }
  338. }
  339. });
  340. }
  341. /**
  342. * @return the AppContextSupport
  343. */
  344. protected AppContextSupport getAppContextSupport() {
  345. AppContextInitializer init = (AppContextInitializer)getContext()
  346. .getBean("applicationInitializer",AppContextInitializer.class);
  347. return init.getAppContextSupport();
  348. }
  349. /**
  350. * @return the RecipeDao
  351. */
  352. protected RecipeDao getRecipeDao() {
  353. return (RecipeDao)getContext().getBean("recipeDao");
  354. }
  355. /**
  356. * @return the MealDao
  357. */
  358. protected MealDao getMealDao() {
  359. return (MealDao)getContext().getBean("mealDao");
  360. }
  361. /**
  362. * @return the BaseDao
  363. */
  364. protected BaseDao getBaseDao() {
  365. return (BaseDao)getContext().getBean("baseDao");
  366. }
  367. /**
  368. * @return the CourseDao
  369. */
  370. protected CourseDao getCourseDao() {
  371. return (CourseDao)getContext().getBean("courseDao");
  372. }
  373. /**
  374. * @return the DifficultyDao
  375. */
  376. protected DifficultyDao getDifficultyDao() {
  377. return (DifficultyDao)getContext().getBean("difficultyDao");
  378. }
  379. /**
  380. * @return the EthnicityDao
  381. */
  382. protected EthnicityDao getEthnicityDao() {
  383. return (EthnicityDao)getContext().getBean("ethnicityDao");
  384. }
  385. /**
  386. * @return the IngredientDao
  387. */
  388. protected IngredientDao getIngredientDao() {
  389. return (IngredientDao)getContext().getBean("ingredientDao");
  390. }
  391. /**
  392. * @return the PrepTimeDao
  393. */
  394. protected PrepTimeDao getPrepTimeDao() {
  395. return (PrepTimeDao)getContext().getBean("prepTimeDao");
  396. }
  397. /**
  398. * @return the UnitDao
  399. */
  400. protected UnitDao getUnitDao() {
  401. return (UnitDao)getContext().getBean("unitDao");
  402. }
  403. /**
  404. * @return a test recipe ID
  405. */
  406. protected Integer getTestRecipeId() {
  407. return getTestIdOrDefault("test.load.recipe.id",DEFAULT_LOAD_ID);
  408. }
  409. /**
  410. * @return a test Base ID
  411. */
  412. protected Integer getTestBaseId() {
  413. return getTestIdOrDefault("test.load.base.id",DEFAULT_LOAD_ID);
  414. }
  415. /**
  416. * @return a test Base
  417. */
  418. protected Base getTestBase() {
  419. return getBaseDao().getBases().get(0);
  420. }
  421. /**
  422. * @return a test Course ID
  423. */
  424. protected Integer getTestCourseId() {
  425. return getTestIdOrDefault("test.load.course.id",DEFAULT_LOAD_ID);
  426. }
  427. /**
  428. * @return a test Difficulty
  429. */
  430. protected Difficulty getTestDifficulty() {
  431. return getDifficultyDao().getDifficulties().get(0);
  432. }
  433. /**
  434. * @return a test Difficulty ID
  435. */
  436. protected Integer getTestDifficultyId() {
  437. return getTestIdOrDefault("test.load.difficulty.id",DEFAULT_LOAD_ID);
  438. }
  439. /**
  440. * @return a test Ethnicity
  441. */
  442. protected Ethnicity getTestEthnicity() {
  443. return getEthnicityDao().getEthnicities().get(0);
  444. }
  445. /**
  446. * @return a test Ehtnicity ID
  447. */
  448. protected Integer getTestEthnicityId() {
  449. return getTestIdOrDefault("test.load.ethnicity.id",DEFAULT_LOAD_ID);
  450. }
  451. /**
  452. * @return a test PrepTime
  453. */
  454. protected PrepTime getTestPrepTime() {
  455. return getPrepTimeDao().getPrepTimes().get(0);
  456. }
  457. /**
  458. * @return a test PrepTime ID
  459. */
  460. protected Integer getTestPrepTimeId() {
  461. return getTestIdOrDefault("test.load.preptime.id",DEFAULT_LOAD_ID);
  462. }
  463. /**
  464. * @return a test System ID
  465. */
  466. protected Integer getTestSystemId() {
  467. return getTestIdOrDefault("test.load.system.id",DEFAULT_LOAD_ID);
  468. }
  469. private Integer getTestIdOrDefault(String key, Integer defaultId) {
  470. try {
  471. return Integer.valueOf(getTestProperty(key));
  472. } catch ( Exception e ) {
  473. // nothing
  474. }
  475. return defaultId;
  476. }
  477. /**
  478. * Get a dummy user.
  479. * @return the dummy user.
  480. */
  481. protected User getDummyUser() {
  482. User u = getDomainObjectFactory().getUserInstance();
  483. u.setAccessLevel(new Integer(1));
  484. u.setCountry(Locale.getDefault().getCountry());
  485. u.setCreatedDate(Calendar.getInstance());
  486. u.setEmail("ieat.test@msqr.us");
  487. u.setLanguage(Locale.getDefault().getLanguage());
  488. u.setLogin(TEST_USER_LOGIN);
  489. u.setName("Test User");
  490. u.setPassword(TEST_USER_PASS);
  491. return u;
  492. }
  493. /**
  494. * @return the UserBiz
  495. */
  496. protected UserBiz getUserBiz() {
  497. return (UserBiz)getContext().getBean("userBiz");
  498. }
  499. /**
  500. * @return the UserDao
  501. */
  502. protected UserDao getUserDao() {
  503. return (UserDao)getContext().getBean("userDao");
  504. }
  505. /**
  506. * @return a test Course
  507. */
  508. protected Course getTestCourse() {
  509. return getCourseDao().getCourses().get(0);
  510. }
  511. /**
  512. * @return the RecipeBiz
  513. */
  514. protected RecipeBiz getRecipeBiz() {
  515. return (RecipeBiz)getContext().getBean("recipeBiz");
  516. }
  517. /**
  518. * @return the RecipeSearchBiz
  519. */
  520. protected RecipeSearchBiz getRecipeSearchBiz() {
  521. return (RecipeSearchBiz)getContext().getBean("recipeSearchBiz");
  522. }
  523. /**
  524. * @return the RecipeSearchIndexBiz
  525. */
  526. protected RecipeSearchIndexBiz getRecipeSearchIndexBiz() {
  527. return (RecipeSearchIndexBiz)getContext().getBean("recipeSearchIndexBiz");
  528. }
  529. }