001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.springframework.beans.factory; 018 019 import java.beans.PropertyEditorSupport; 020 import java.util.StringTokenizer; 021 022 import junit.framework.TestCase; 023 024 import org.springframework.beans.BeansException; 025 import org.springframework.beans.FatalBeanException; 026 import org.springframework.beans.PropertyAccessExceptionsException; 027 import org.springframework.beans.TestBean; 028 import org.springframework.beans.factory.support.AbstractBeanFactory; 029 030 /** 031 * Subclasses must implement setUp() to initialize bean factory 032 * and any other variables they need. 033 * @author Rod Johnson 034 */ 035 public abstract class AbstractBeanFactoryTests extends TestCase { 036 037 protected abstract BeanFactory getBeanFactory(); 038 039 /** 040 * Roderick beans inherits from rod, 041 * overriding name only. 042 */ 043 public void testInheritance() { 044 assertTrue(getBeanFactory().containsBean("rod")); 045 assertTrue(getBeanFactory().containsBean("roderick")); 046 TestBean rod = (TestBean) getBeanFactory().getBean("rod"); 047 TestBean roderick = (TestBean) getBeanFactory().getBean("roderick"); 048 assertTrue("not == ", rod != roderick); 049 assertTrue("rod.name is Rod", rod.getName().equals("Rod")); 050 assertTrue("rod.age is 31", rod.getAge() == 31); 051 assertTrue("roderick.name is Roderick", roderick.getName().equals("Roderick")); 052 assertTrue("roderick.age was inherited", roderick.getAge() == rod.getAge()); 053 } 054 055 public void testGetBeanWithNullArg() { 056 try { 057 getBeanFactory().getBean(null); 058 fail("Can't get null bean"); 059 } 060 catch (IllegalArgumentException ex) { 061 // OK 062 } 063 } 064 065 /** 066 * Test that InitializingBean objects receive the 067 * afterPropertiesSet() callback 068 */ 069 public void testInitializingBeanCallback() { 070 MustBeInitialized mbi = (MustBeInitialized) getBeanFactory().getBean("mustBeInitialized"); 071 // The dummy business method will throw an exception if the 072 // afterPropertiesSet() callback wasn't invoked 073 mbi.businessMethod(); 074 } 075 076 /** 077 * Test that InitializingBean/BeanFactoryAware/DisposableBean objects receive the 078 * afterPropertiesSet() callback before BeanFactoryAware callbacks 079 */ 080 public void testLifecycleCallbacks() { 081 LifecycleBean lb = (LifecycleBean) getBeanFactory().getBean("lifecycle"); 082 assertEquals("lifecycle", lb.getBeanName()); 083 // The dummy business method will throw an exception if the 084 // necessary callbacks weren't invoked in the right order. 085 lb.businessMethod(); 086 assertTrue("Not destroyed", !lb.isDestroyed()); 087 } 088 089 public void testFindsValidInstance() { 090 try { 091 Object o = getBeanFactory().getBean("rod"); 092 assertTrue("Rod bean is a TestBean", o instanceof TestBean); 093 TestBean rod = (TestBean) o; 094 assertTrue("rod.name is Rod", rod.getName().equals("Rod")); 095 assertTrue("rod.age is 31", rod.getAge() == 31); 096 } 097 catch (Exception ex) { Rate098 ex.printStackTrace(); 099 fail("Shouldn't throw exception on getting valid instance"); 100 } 101 } 102 103 public void testGetInstanceByMatchingClass() { 104 try { 105 Object o = getBeanFactory().getBean("rod", TestBean.class); 106 assertTrue("Rod bean is a TestBean", o instanceof TestBean); 107 } 108 catch (Exception ex) { Rate109 ex.printStackTrace(); 110 fail("Shouldn't throw exception on getting valid instance with matching class"); 111 } 112 } 113 114 public void testGetInstanceByNonmatchingClass() { 115 try { 116 Object o = getBeanFactory().getBean("rod", BeanFactory.class); 117 fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException"); 118 } 119 catch (BeanNotOfRequiredTypeException ex) { 120 // So far, so good 121 assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod")); 122 assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class)); 123 assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType())); 124 assertTrue("Actual type is correct", ex.getActualType() == getBeanFactory().getBean("rod").getClass()); 125 } 126 catch (Exception ex) { Rate127 ex.printStackTrace(); 128 fail("Shouldn't throw exception on getting valid instance"); 129 } 130 } 131 132 public void testGetSharedInstanceByMatchingClass() { 133 try { 134 Object o = getBeanFactory().getBean("rod", TestBean.class); 135 assertTrue("Rod bean is a TestBean", o instanceof TestBean); 136 } 137 catch (Exception ex) { Rate138 ex.printStackTrace(); 139 fail("Shouldn't throw exception on getting valid instance with matching class"); 140 } 141 } 142 143 public void testGetSharedInstanceByMatchingClassNoCatch() { 144 Object o = getBeanFactory().getBean("rod", TestBean.class); 145 assertTrue("Rod bean is a TestBean", o instanceof TestBean); 146 } 147 148 public void testGetSharedInstanceByNonmatchingClass() { 149 try { 150 Object o = getBeanFactory().getBean("rod", BeanFactory.class); 151 fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException"); 152 } 153 catch (BeanNotOfRequiredTypeException ex) { 154 // So far, so good 155 assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod")); 156 assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class)); 157 assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType())); 158 } 159 catch (Exception ex) { Rate160 ex.printStackTrace(); 161 fail("Shouldn't throw exception on getting valid instance"); 162 } 163 } 164 165 public void testSharedInstancesAreEqual() { 166 try { 167 Object o = getBeanFactory().getBean("rod"); 168 assertTrue("Rod bean1 is a TestBean", o instanceof TestBean); 169 Object o1 = getBeanFactory().getBean("rod"); 170 assertTrue("Rod bean2 is a TestBean", o1 instanceof TestBean); 171 assertTrue("Object equals applies", o == o1); 172 } 173 catch (Exception ex) { Rate174 ex.printStackTrace(); 175 fail("Shouldn't throw exception on getting valid instance"); 176 } 177 } 178 179 public void testPrototypeInstancesAreIndependent() { 180 TestBean tb1 = (TestBean) getBeanFactory().getBean("kathy"); 181 TestBean tb2 = (TestBean) getBeanFactory().getBean("kathy"); 182 assertTrue("ref equal DOES NOT apply", tb1 != tb2); 183 assertTrue("object equal true", tb1.equals(tb2)); 184 tb1.setAge(1); 185 tb2.setAge(2); 186 assertTrue("1 age independent = 1", tb1.getAge() == 1); 187 assertTrue("2 age independent = 2", tb2.getAge() == 2); 188 assertTrue("object equal now false", !tb1.equals(tb2)); 189 } 190 191 public void testNotThere() { 192 assertFalse(getBeanFactory().containsBean("Mr Squiggle")); 193 try { 194 Object o = getBeanFactory().getBean("Mr Squiggle"); 195 fail("Can't find missing bean"); 196 } 197 catch (BeansException ex) { 198 //ex.printStackTrace(); 199 //fail("Shouldn't throw exception on getting valid instance"); 200 } 201 } 202 203 public void testValidEmpty() { 204 try { 205 Object o = getBeanFactory().getBean("validEmpty"); 206 assertTrue("validEmpty bean is a TestBean", o instanceof TestBean); 207 TestBean ve = (TestBean) o; 208 assertTrue("Valid empty has defaults", ve.getName() == null && ve.getAge() == 0 && ve.getSpouse() == null); 209 } 210 catch (BeansException ex) { 211 ex.printStackTrace(); 212 fail("Shouldn't throw exception on valid empty"); 213 } 214 } 215 216 public void testTypeMismatch() { 217 try { 218 Object o = getBeanFactory().getBean("typeMismatch"); 219 fail("Shouldn't succeed with type mismatch"); 220 } 221 catch (BeanCreationException wex) { 222 assertEquals("typeMismatch", wex.getBeanName()); 223 assertTrue(wex.getCause() instanceof PropertyAccessExceptionsException); 224 PropertyAccessExceptionsException ex = (PropertyAccessExceptionsException) wex.getCause(); 225 // Further tests 226 assertTrue("Has one error ", ex.getExceptionCount() == 1); 227 assertTrue("Error is for field age", ex.getPropertyAccessException("age") != null); 228 229 TestBean tb = (TestBean) ex.getBeanWrapper().getWrappedInstance(); 230 assertTrue("Age still has default", tb.getAge() == 0); 231 assertTrue("We have rejected age in exception", ex.getPropertyAccessException("age").getPropertyChangeEvent().getNewValue().equals("34x")); 232 assertTrue("valid name stuck", tb.getName().equals("typeMismatch")); 233 assertTrue("valid spouse stuck", tb.getSpouse().getName().equals("Rod")); 234 } 235 } 236 237 public void testGrandparentDefinitionFoundInBeanFactory() throws Exception { 238 TestBean dad = (TestBean) getBeanFactory().getBean("father"); 239 assertTrue("Dad has correct name", dad.getName().equals("Albert")); 240 } 241 242 public void testFactorySingleton() throws Exception { 243 assertTrue(getBeanFactory().isSingleton("&singletonFactory")); 244 assertTrue(getBeanFactory().isSingleton("singletonFactory")); 245 TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory"); 246 assertTrue("Singleton from factory has correct name, not " + tb.getName(), tb.getName().equals(DummyFactory.SINGLETON_NAME)); 247 DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); 248 TestBean tb2 = (TestBean) getBeanFactory().getBean("singletonFactory"); 249 assertTrue("Singleton references ==", tb == tb2); 250 assertTrue("FactoryBean is BeanFactoryAware", factory.getBeanFactory() != null); 251 } 252 253 public void testFactoryPrototype() throws Exception { 254 assertTrue(getBeanFactory().isSingleton("&prototypeFactory")); 255 assertFalse(getBeanFactory().isSingleton("prototypeFactory")); 256 TestBean tb = (TestBean) getBeanFactory().getBean("prototypeFactory"); 257 assertTrue(!tb.getName().equals(DummyFactory.SINGLETON_NAME)); 258 TestBean tb2 = (TestBean) getBeanFactory().getBean("prototypeFactory"); 259 assertTrue("Prototype references !=", tb != tb2); 260 } 261 262 /** 263 * Check that we can get the factory bean itself. 264 * This is only possible if we're dealing with a factory 265 * @throws Exception 266 */ 267 public void testGetFactoryItself() throws Exception { 268 DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); 269 assertTrue(factory != null); 270 } 271 272 /** 273 * Check that afterPropertiesSet gets called on factory 274 * @throws Exception 275 */ 276 public void testFactoryIsInitialized() throws Exception { 277 TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory"); 278 DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); 279 assertTrue("Factory was initialized because it implemented InitializingBean", factory.wasInitialized()); 280 } 281 282 /** 283 * It should be illegal to dereference a normal bean 284 * as a factory 285 */ 286 public void testRejectsFactoryGetOnNormalBean() { 287 try { 288 getBeanFactory().getBean("&rod"); 289 fail("Shouldn't permit factory get on normal bean"); 290 } 291 catch (BeanIsNotAFactoryException ex) { 292 // Ok 293 } 294 } 295 296 // TODO: refactor in AbstractBeanFactory (tests for AbstractBeanFactory) 297 // and rename this class 298 public void testAliasing() { 299 if (!(getBeanFactory() instanceof AbstractBeanFactory)) 300 return; 301 302 String alias = "rods alias"; 303 try { 304 getBeanFactory().getBean(alias); 305 fail("Shouldn't permit factory get on normal bean"); 306 } 307 catch (NoSuchBeanDefinitionException ex) { 308 // Ok 309 assertTrue(alias.equals(ex.getBeanName())); 310 } 311 312 // Create alias 313 ((AbstractBeanFactory) getBeanFactory()).registerAlias("rod", alias); 314 Object rod = getBeanFactory().getBean("rod"); 315 Object aliasRod = getBeanFactory().getBean(alias); 316 assertTrue(rod == aliasRod); 317 318 try { 319 ((AbstractBeanFactory) getBeanFactory()).registerAlias("father", alias); 320 fail("Should have thrown FatalBeanException"); 321 } 322 catch (FatalBeanException ex) { 323 // expected 324 } 325 326 // TODO: check prototype support 327 } 328 329 330 public static class TestBeanEditor extends PropertyEditorSupport { 331 332 public void setAsText(String text) { 333 TestBean tb = new TestBean(); 334 StringTokenizer st = new StringTokenizer(text, "_"); 335 tb.setName(st.nextToken()); 336 tb.setAge(Integer.parseInt(st.nextToken())); 337 setValue(tb); 338 } 339 } 340 341 }