001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.spring.test; 018 019import java.io.IOException; 020import java.io.Serializable; 021import java.lang.annotation.Annotation; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.Iterator; 025import java.util.Locale; 026import java.util.Map; 027import java.util.Map.Entry; 028 029import org.springframework.beans.BeansException; 030import org.springframework.beans.factory.BeanFactory; 031import org.springframework.beans.factory.BeanNotOfRequiredTypeException; 032import org.springframework.beans.factory.FactoryBean; 033import org.springframework.beans.factory.NoSuchBeanDefinitionException; 034import org.springframework.beans.factory.ObjectProvider; 035import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 036import org.springframework.context.ApplicationContext; 037import org.springframework.context.ApplicationEvent; 038import org.springframework.context.MessageSourceResolvable; 039import org.springframework.context.NoSuchMessageException; 040import org.springframework.core.ResolvableType; 041import org.springframework.core.env.Environment; 042import org.springframework.core.io.Resource; 043 044/** 045 * Mock application context object. This mock context allows easy creation of unit tests by allowing 046 * the user to put bean instances into the context. 047 * 048 * Only {@link #getBean(String)}, {@link #getBean(String, Class)}, and 049 * {@link #getBeansOfType(Class) 050 * } are implemented so far. Any other method throws 051 * {@link UnsupportedOperationException}. 052 * 053 * @author Igor Vaynberg (ivaynberg) 054 * 055 */ 056public class ApplicationContextMock implements ApplicationContext, Serializable 057{ 058 private static final long serialVersionUID = 1L; 059 060 private final Map<String, Object> beans = new HashMap<>(); 061 062 /** 063 * puts bean with the given name into the context 064 * 065 * @param name 066 * @param bean 067 */ 068 public void putBean(final String name, final Object bean) 069 { 070 if (beans.containsKey(name)) 071 { 072 throw new IllegalArgumentException("a bean with name [" + name + 073 "] has already been added to the context"); 074 } 075 beans.put(name, bean); 076 } 077 078 /** 079 * puts bean with into the context. bean object's class name will be used as the bean name. 080 * 081 * @param bean 082 */ 083 public void putBean(final Object bean) 084 { 085 putBean(bean.getClass().getName(), bean); 086 } 087 088 @Override 089 public Object getBean(final String name) throws BeansException 090 { 091 Object bean = beans.get(name); 092 if (bean == null) 093 { 094 throw new NoSuchBeanDefinitionException(name); 095 } 096 return bean; 097 } 098 099 @Override 100 public Object getBean(final String name, final Object... args) throws BeansException 101 { 102 return getBean(name); 103 } 104 105 /** 106 * @see org.springframework.beans.factory.BeanFactory#getBean(java.lang.String, java.lang.Class) 107 */ 108 @Override 109 @SuppressWarnings({ "unchecked" }) 110 public <T> T getBean(String name, Class<T> requiredType) throws BeansException 111 { 112 Object bean = getBean(name); 113 if (!(requiredType.isAssignableFrom(bean.getClass()))) 114 { 115 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 116 } 117 return (T)bean; 118 } 119 120 /** 121 * @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(java.lang.Class) 122 */ 123 @Override 124 @SuppressWarnings({ "unchecked" }) 125 public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException 126 { 127 final Map<String, T> found = new HashMap<>(); 128 129 for (Entry<String, Object> entry : beans.entrySet()) 130 { 131 if (type.isAssignableFrom(entry.getValue().getClass())) 132 { 133 found.put(entry.getKey(), (T)entry.getValue()); 134 } 135 } 136 137 return found; 138 } 139 140 @Override 141 public <T> T getBean(Class<T> requiredType) throws BeansException 142 { 143 Iterator<T> beans = getBeansOfType(requiredType).values().iterator(); 144 145 if (beans.hasNext() == false) 146 { 147 throw new NoSuchBeanDefinitionException("bean of required type " + requiredType + 148 " not found"); 149 } 150 final T bean = beans.next(); 151 152 if (beans.hasNext() != false) 153 { 154 throw new NoSuchBeanDefinitionException("more than one bean of required type " + 155 requiredType + " found"); 156 } 157 return bean; 158 } 159 160 @Override 161 public <T> T getBean(Class<T> requiredType, Object... objects) throws BeansException 162 { 163 return getBean(requiredType); 164 } 165 166 @Override 167 public <T> ObjectProvider<T> getBeanProvider(Class<T> aClass) 168 { 169 return null; 170 } 171 172 @Override 173 public <T> ObjectProvider<T> getBeanProvider(ResolvableType resolvableType) 174 { 175 return null; 176 } 177 178 @Override 179 public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) 180 throws BeansException 181 { 182 final Map<String, Object> found = new HashMap<>(); 183 184 for (Entry<String, Object> entry : beans.entrySet()) 185 { 186 if (entry.getValue().getClass().isAnnotationPresent(annotationType)) 187 { 188 found.put(entry.getKey(), entry.getValue()); 189 } 190 } 191 return found; 192 } 193 194 @Override 195 public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) 196 { 197 return findAnnotationOnClass(getBean(beanName).getClass(), annotationType); 198 } 199 200 @Override 201 public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException { 202 return findAnnotationOnClass(getBean(beanName).getClass(), annotationType); 203 } 204 205 private <A extends Annotation> A findAnnotationOnClass(Class<?> cls, Class<A> annotationType) 206 { 207 // lookup annotation type on class 208 A annotation = cls.getAnnotation(annotationType); 209 210 // lookup annotation type on superclass 211 if (annotation == null && cls.getSuperclass() != null) 212 { 213 annotation = findAnnotationOnClass(cls.getSuperclass(), annotationType); 214 } 215 216 // lookup annotation type on interfaces 217 if (annotation == null) 218 { 219 for (Class<?> intfClass : cls.getInterfaces()) 220 { 221 annotation = findAnnotationOnClass(intfClass, annotationType); 222 223 if (annotation != null) 224 { 225 break; 226 } 227 } 228 } 229 230 return annotation; 231 } 232 233 @Override 234 public ApplicationContext getParent() 235 { 236 throw new UnsupportedOperationException(); 237 } 238 239 @Override 240 public String getDisplayName() 241 { 242 throw new UnsupportedOperationException(); 243 } 244 245 @Override 246 public long getStartupDate() 247 { 248 throw new UnsupportedOperationException(); 249 } 250 251 @Override 252 public void publishEvent(final ApplicationEvent event) 253 { 254 throw new UnsupportedOperationException(); 255 } 256 257 @Override 258 public void publishEvent(Object o) 259 { 260 throw new UnsupportedOperationException(); 261 } 262 263 @Override 264 public boolean containsBeanDefinition(final String beanName) 265 { 266 return containsBean(beanName); 267 } 268 269 @Override 270 public int getBeanDefinitionCount() 271 { 272 return beans.size(); 273 } 274 275 @Override 276 public String[] getBeanDefinitionNames() 277 { 278 return beans.keySet().toArray(new String[0]); 279 } 280 281 @Override 282 public <T> ObjectProvider<T> getBeanProvider(final Class<T> aClass, final boolean b) { 283 return null; 284 } 285 286 @Override 287 public <T> ObjectProvider<T> getBeanProvider(final ResolvableType resolvableType, final boolean b) { 288 return null; 289 } 290 291 @Override 292 public String[] getBeanNamesForType(ResolvableType resolvableType) 293 { 294 return new String[0]; 295 } 296 297 @Override 298 public String[] getBeanNamesForType(ResolvableType resolvableType, boolean includeNonSingletons, boolean allowEagerInit) 299 { 300 return new String[0]; 301 } 302 303 @Override 304 @SuppressWarnings({ "unchecked" }) 305 public String[] getBeanNamesForType(final Class type) 306 { 307 ArrayList<String> names = new ArrayList<>(); 308 for (Entry<String, Object> entry : beans.entrySet()) 309 { 310 Object bean = entry.getValue(); 311 312 if (type.isAssignableFrom(bean.getClass())) 313 { 314 names.add(entry.getKey()); 315 } 316 } 317 return names.toArray(new String[names.size()]); 318 } 319 320 @Override 321 @SuppressWarnings({ "unchecked" }) 322 public String[] getBeanNamesForType(Class type, boolean includeNonSingletons, 323 boolean allowEagerInit) 324 { 325 throw new UnsupportedOperationException(); 326 } 327 328 @Override 329 public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, 330 boolean allowEagerInit) throws BeansException 331 { 332 throw new UnsupportedOperationException(); 333 } 334 335 @Override 336 public String[] getBeanNamesForAnnotation(Class<? extends Annotation> aClass) 337 { 338 throw new UnsupportedOperationException(); 339 } 340 341 @Override 342 public boolean containsBean(final String name) 343 { 344 return beans.containsKey(name); 345 } 346 347 @Override 348 public boolean isSingleton(final String name) throws NoSuchBeanDefinitionException 349 { 350 return true; 351 } 352 353 @Override 354 public Class<?> getType(final String name) throws NoSuchBeanDefinitionException 355 { 356 return getType(name, true); 357 } 358 359 @Override 360 public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException 361 { 362 Object bean = beans.get(name); 363 if (bean == null) 364 { 365 throw new NoSuchBeanDefinitionException("No bean with name '" + name + "'"); 366 } 367 368 if (bean instanceof FactoryBean) 369 { 370 return ((FactoryBean) bean).getObjectType(); 371 } 372 373 return bean.getClass(); 374 } 375 376 @Override 377 public String[] getAliases(final String name) throws NoSuchBeanDefinitionException 378 { 379 throw new UnsupportedOperationException(); 380 } 381 382 /** 383 * @see org.springframework.beans.factory.HierarchicalBeanFactory#getParentBeanFactory() 384 */ 385 @Override 386 public BeanFactory getParentBeanFactory() 387 { 388 return null; 389 } 390 391 @Override 392 public String getMessage(final String code, final Object[] args, final String defaultMessage, 393 final Locale locale) 394 { 395 throw new UnsupportedOperationException(); 396 } 397 398 @Override 399 public String getMessage(final String code, final Object[] args, final Locale locale) 400 throws NoSuchMessageException 401 { 402 throw new UnsupportedOperationException(); 403 } 404 405 @Override 406 public String getMessage(final MessageSourceResolvable resolvable, final Locale locale) 407 throws NoSuchMessageException 408 { 409 throw new UnsupportedOperationException(); 410 } 411 412 @Override 413 public Resource[] getResources(final String locationPattern) throws IOException 414 { 415 throw new UnsupportedOperationException(); 416 } 417 418 @Override 419 public Resource getResource(final String location) 420 { 421 throw new UnsupportedOperationException(); 422 } 423 424 @Override 425 public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException 426 { 427 throw new UnsupportedOperationException(); 428 } 429 430 @Override 431 public boolean containsLocalBean(final String arg0) 432 { 433 throw new UnsupportedOperationException(); 434 } 435 436 @Override 437 public ClassLoader getClassLoader() 438 { 439 throw new UnsupportedOperationException(); 440 } 441 442 @Override 443 public String getId() 444 { 445 return null; 446 } 447 448 @Override 449 public String getApplicationName() 450 { 451 return ""; 452 } 453 454 @Override 455 public boolean isPrototype(final String name) throws NoSuchBeanDefinitionException 456 { 457 return !isSingleton(name); 458 } 459 460 @Override 461 public boolean isTypeMatch(String s, ResolvableType resolvableType) throws NoSuchBeanDefinitionException 462 { 463 return false; 464 } 465 466 @Override 467 @SuppressWarnings({ "unchecked" }) 468 public boolean isTypeMatch(final String name, final Class targetType) 469 throws NoSuchBeanDefinitionException 470 { 471 throw new UnsupportedOperationException(); 472 } 473 474 @Override 475 public Environment getEnvironment() 476 { 477 return null; 478 } 479}