moving unit tests from .testsuite -> .context

This commit is contained in:
Chris Beams
2008-12-14 21:46:55 +00:00
parent 931728ba2f
commit 2359942dd7
15 changed files with 615 additions and 52 deletions

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Bean exposing a map. Used for bean factory tests.
*
* @author Rod Johnson
* @since 05.06.2003
*/
public class HasMap {
private Map map;
private Set set;
private Properties props;
private Object[] objectArray;
private Class[] classArray;
private Integer[] intArray;
private HasMap() {
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Properties getProps() {
return props;
}
public void setProps(Properties props) {
this.props = props;
}
public Object[] getObjectArray() {
return objectArray;
}
public void setObjectArray(Object[] objectArray) {
this.objectArray = objectArray;
}
public Class[] getClassArray() {
return classArray;
}
public void setClassArray(Class[] classArray) {
this.classArray = classArray;
}
public Integer[] getIntegerArray() {
return intArray;
}
public void setIntegerArray(Integer[] is) {
intArray = is;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import java.util.Map;
import java.util.Set;
/**
* @author Chris Beams
*/
public class MapAndSet {
private Object obj;
public MapAndSet(Map map) {
this.obj = map;
}
public MapAndSet(Set set) {
this.obj = set;
}
public Object getObject() {
return obj;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import java.util.Collection;
/**
* Bean that exposes a simple property that can be set
* to a mix of references and individual values.
*
* @author Rod Johnson
* @since 27.05.2003
*/
public class MixedCollectionBean {
private Collection jumble;
public void setJumble(Collection jumble) {
this.jumble = jumble;
}
public Collection getJumble() {
return jumble;
}
}

View File

@@ -0,0 +1,374 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="jenny" class="org.springframework.beans.TestBean">
<property name="name"><value>Jenny</value></property>
<property name="age"><value>30</value></property>
<property name="spouse">
<!-- Could use id and href -->
<ref local="david"/>
</property>
</bean>
<bean id="david" class="org.springframework.beans.TestBean">
<description>
Simple bean, without any collections.
</description>
<property name="name">
<description>The name of the user</description>
<value>David</value>
</property>
<property name="age"><value>27</value></property>
</bean>
<bean id="rod" class="org.springframework.beans.TestBean">
<property name="name"><value>Rod</value></property>
<property name="age"><value>32</value></property>
<property name="friends">
<description>List of Rod's friends</description>
<list>
<ref local="jenny"/>
<ref local="david"/>
</list>
</property>
</bean>
<bean id="pJenny" class="org.springframework.beans.TestBean" scope="prototype">
<property name="name"><value>Jenny</value></property>
<property name="age"><value>30</value></property>
<property name="spouse">
<!-- Could use id and href -->
<ref local="david"/>
</property>
</bean>
<bean id="pDavid" class="org.springframework.beans.TestBean" scope="prototype">
<property name="name"><value>David</value></property>
<property name="age"><value>27</value></property>
</bean>
<bean id="pRod" class="org.springframework.beans.TestBean" scope="prototype">
<property name="name"><value>Rod</value></property>
<property name="age"><value>32</value></property>
<property name="friends">
<list>
<ref local="pJenny"/>
<ref local="pDavid"/>
</list>
</property>
</bean>
<!--
Try setting a collection property to a single value
-->
<bean id="loner" class="org.springframework.beans.TestBean">
<property name="name"><value>loner</value></property>
<property name="age"><value>26</value></property>
<property name="friends">
<list>
<description>My List</description>
<ref local="david"/>
</list>
</property>
</bean>
<bean id="jumble" class="org.springframework.beans.factory.xml.MixedCollectionBean">
<property name="jumble">
<list>
<ref local="david"/>
<value>literal</value>
<ref local="jenny"/>
<idref local="rod"/>
</list>
</property>
</bean>
<bean id="jumble2" class="org.springframework.beans.factory.xml.MixedCollectionBean" lazy-init="true">
<property name="jumble">
<list>
<ref local="david"/>
<value>literal</value>
<ref local="jenny"/>
<idref bean="rod"/>
<idref bean="rod2"/>
</list>
</property>
</bean>
<bean id="verbose" class="org.springframework.beans.TestBean">
<property name="name"><value>verbose</value></property>
</bean>
<bean id="verbose2" class="org.springframework.beans.TestBean">
<property name="name"><idref local="verbose"/></property>
</bean>
<bean id="verbose3" class="org.springframework.beans.TestBean">
<property name="name"><idref bean="verbose"/></property>
</bean>
<bean id="emptyMap" class="org.springframework.beans.factory.HasMap">
<property name="map">
<map>
</map>
</property>
</bean>
<bean id="literalMap" class="org.springframework.beans.factory.HasMap">
<property name="map">
<map>
<entry key="foo" value="bar"/>
<entry key="fi" value="fum"/>
<entry key="fa"><null/></entry>
</map>
</property>
</bean>
<bean id="mixedMap" class="org.springframework.beans.factory.HasMap">
<property name="map">
<map>
<entry key-ref="fooKey">
<value type="java.lang.Integer">10</value>
</entry>
<entry>
<key>
<ref bean="jennyKey"/>
</key>
<ref local="jenny"/>
</entry>
<entry>
<key>
<bean class="java.lang.Integer">
<constructor-arg value="5"/>
</bean>
</key>
<idref bean="david"/>
</entry>
</map>
</property>
</bean>
<bean id="fooKey" class="java.lang.String">
<constructor-arg value="foo"/>
</bean>
<bean id="jennyKey" class="java.lang.String">
<constructor-arg value="jenny"/>
</bean>
<bean id="pMixedMap" class="org.springframework.beans.factory.HasMap" scope="prototype">
<property name="map">
<map>
<entry key="foo" value="bar"/>
<entry key="jenny" value-ref="pJenny"/>
</map>
</property>
</bean>
<bean id="mixedMapWithList" class="org.springframework.beans.factory.HasMap">
<property name="map">
<map>
<entry>
<key><null/></key>
<value>bar</value>
</entry>
<entry key="jenny"><ref local="jenny"/></entry>
<entry key="list">
<list>
<value>zero</value>
<map>
<entry key="fo"><value>bar</value></entry>
<entry key="jen"><ref local="jenny"/></entry>
</map>
<list>
<ref local="jenny"/>
<value>ba</value>
</list>
<null/>
</list>
</entry>
<entry key="map">
<map>
<entry key="foo"><value>bar</value></entry>
<entry key="jenny"><ref local="jenny"/></entry>
</map>
</entry>
</map>
</property>
</bean>
<bean id="emptySet" class="org.springframework.beans.factory.HasMap">
<property name="set">
<set>
</set>
</property>
</bean>
<bean id="set" class="org.springframework.beans.factory.HasMap">
<property name="set">
<set>
<value>bar</value>
<ref local="jenny"/>
<null/>
</set>
</property>
</bean>
<bean id="emptyProps" class="org.springframework.beans.factory.HasMap">
<property name="props">
<props>
</props>
</property>
</bean>
<bean id="props" class="org.springframework.beans.factory.HasMap">
<property name="props">
<props>
<prop key="foo">bar</prop>
<prop key="2">TWO</prop>
</props>
</property>
</bean>
<bean id="propsViaMap" class="org.springframework.beans.factory.HasMap">
<property name="props">
<map>
<entry key="foo" value="bar"/>
<entry key="2" value="TWO"/>
</map>
</property>
</bean>
<bean id="objectArray" class="org.springframework.beans.factory.HasMap">
<property name="objectArray">
<list>
<value>one</value>
<ref local="jenny"/>
</list>
</property>
</bean>
<bean id="classArray" class="org.springframework.beans.factory.HasMap">
<property name="classArray">
<list>
<value>java.lang.String</value>
<value>java.lang.Exception</value>
</list>
</property>
</bean>
<bean id="integerArray" class="org.springframework.beans.factory.HasMap">
<property name="integerArray">
<list>
<value>0</value>
<value>1</value>
<value>2</value>
</list>
</property>
</bean>
<bean id="listFactory" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>bar</value>
<value>jenny</value>
</list>
</property>
<property name="targetListClass">
<value>java.util.LinkedList</value>
</property>
</bean>
<bean id="pListFactory" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>bar</value>
<value>jenny</value>
</list>
</property>
<property name="targetListClass">
<value>java.util.LinkedList</value>
</property>
<property name="singleton">
<value>true</value>
</property>
</bean>
<bean id="setFactory" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>bar</value>
<value>jenny</value>
</set>
</property>
<property name="targetSetClass">
<value>java.util.TreeSet</value>
</property>
</bean>
<bean id="pSetFactory" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>bar</value>
<value>jenny</value>
</set>
</property>
<property name="targetSetClass">
<value>java.util.TreeSet</value>
</property>
<property name="singleton">
<value>true</value>
</property>
</bean>
<bean id="mapFactory" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="foo"><value>bar</value></entry>
<entry key="jen"><value>jenny</value></entry>
</map>
</property>
<property name="targetMapClass">
<value>java.util.TreeMap</value>
</property>
</bean>
<bean id="pMapFactory" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="foo"><value>bar</value></entry>
<entry key="jen"><value>jenny</value></entry>
</map>
</property>
<property name="targetMapClass">
<value>java.util.TreeMap</value>
</property>
<property name="singleton">
<value>true</value>
</property>
</bean>
<bean id="setAndMap" class="org.springframework.beans.factory.xml.MapAndSet">
<constructor-arg>
<map>
<description>My Map</description>
<entry key="key1" value="val1"/>
<entry key="key2" value="val2"/>
<entry key="key3" value="val3"/>
</map>
</constructor-arg>
</bean>
<bean id="enumSetFactory" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<description>My Set</description>
</set>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="inheritedTestBean" class="org.springframework.beans.TestBean" abstract="true">
<property name="name"><value>parent</value></property>
<property name="age"><value>1</value></property>
</bean>
<bean id="inheritedTestBeanWithoutClass" abstract="true">
<property name="name"><value>parent</value></property>
<property name="age"><value>1</value></property>
</bean>
<bean id="inheritedTestBeanPrototype" class="org.springframework.beans.TestBean" scope="prototype">
<property name="name"><value>parent</value></property>
<property name="age"><value>2</value></property>
</bean>
<bean id="inheritedTestBeanSingleton" class="org.springframework.beans.TestBean"/>
</beans>

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.access;
import junit.framework.TestCase;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BootstrapException;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
/**
* @author Colin Sampaleanu
*/
public class ContextJndiBeanFactoryLocatorTests extends TestCase {
public static final String BEAN_FACTORY_PATH_ENVIRONMENT_KEY = "java:comp/env/ejb/BeanFactoryPath";
public void testBeanFactoryPathRequiredFromJndiEnvironment() throws Exception {
// Set up initial context but don't bind anything
SimpleNamingContextBuilder.emptyActivatedContextBuilder();
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BootstrapException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(BEAN_FACTORY_PATH_ENVIRONMENT_KEY) != -1);
}
}
public void testBeanFactoryPathFromJndiEnvironmentNotFound() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String bogusPath = "RUBBISH/com/xxxx/framework/server/test1.xml";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, bogusPath);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BeansException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(bogusPath) != -1);
}
}
public void testBeanFactoryPathFromJndiEnvironmentNotValidXml() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String nonXmlPath = "com/xxxx/framework/server/SlsbEndpointBean.class";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, nonXmlPath);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BeansException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(nonXmlPath) != -1);
}
}
public void testBeanFactoryPathFromJndiEnvironmentWithSingleFile() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String path = "org/springframework/beans/factory/xml/collections.xml";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, path);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
assertTrue(bf.containsBean("rod"));
assertTrue(bf instanceof ApplicationContext);
}
public void testBeanFactoryPathFromJndiEnvironmentWithMultipleFiles() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String path = "/org/springframework/beans/factory/xml/collections.xml /org/springframework/beans/factory/xml/parent.xml";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, path);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
assertTrue(bf.containsBean("rod"));
assertTrue(bf.containsBean("inheritedTestBean"));
}
}

View File

@@ -0,0 +1,441 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import static org.junit.Assert.*;
import org.aspectj.lang.annotation.Aspect;
import org.junit.Test;
import org.springframework.beans.TestBean;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation2.NamedStubDao2;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.stereotype.Component;
import example.scannable.CustomComponent;
import example.scannable.FooService;
import example.scannable.FooServiceImpl;
import example.scannable.NamedStubDao;
import example.scannable.StubFooDao;
/**
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
*/
public class ClassPathBeanDefinitionScannerTests {
private static final String BASE_PACKAGE = "example.scannable";
@Test
public void testSimpleScanWithDefaultFiltersAndPostProcessors() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(9, beanCount);
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean("thoreau"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testDoubleScan() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(9, beanCount);
scanner.scan(BASE_PACKAGE);
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean("thoreau"));
}
@Test
public void testSimpleScanWithDefaultFiltersAndNoPostProcessors() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(6, beanCount);
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
}
@Test
public void testSimpleScanWithDefaultFiltersAndOverridingBean() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("stubFooDao", new RootBeanDefinition(TestBean.class));
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
// should not fail!
scanner.scan(BASE_PACKAGE);
}
@Test
public void testSimpleScanWithDefaultFiltersAndDefaultBeanNameClash() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
try {
scanner.scan("org.springframework.context.annotation3");
scanner.scan(BASE_PACKAGE);
fail("Should have thrown IllegalStateException");
}
catch (IllegalStateException ex) {
// expected
assertTrue(ex.getMessage().indexOf("stubFooDao") != -1);
assertTrue(ex.getMessage().indexOf(StubFooDao.class.getName()) != -1);
}
}
@Test
public void testSimpleScanWithDefaultFiltersAndOverriddenEqualNamedBean() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("myNamedDao", new RootBeanDefinition(NamedStubDao.class));
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(5, beanCount);
assertEquals(6, context.getBeanDefinitionCount());
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
}
@Test
public void testSimpleScanWithDefaultFiltersAndOverriddenCompatibleNamedBean() {
GenericApplicationContext context = new GenericApplicationContext();
RootBeanDefinition bd = new RootBeanDefinition(NamedStubDao.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
context.registerBeanDefinition("myNamedDao", bd);
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(5, beanCount);
assertEquals(6, context.getBeanDefinitionCount());
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
}
@Test
public void testSimpleScanWithDefaultFiltersAndSameBeanTwice() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
// should not fail!
scanner.scan(BASE_PACKAGE);
scanner.scan(BASE_PACKAGE);
}
@Test
public void testSimpleScanWithDefaultFiltersAndSpecifiedBeanNameClash() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
try {
scanner.scan("org.springframework.context.annotation2");
scanner.scan(BASE_PACKAGE);
fail("Must have thrown IllegalStateException");
}
catch (IllegalStateException expected) {
assertTrue(expected.getMessage().contains("myNamedDao"));
assertTrue(expected.getMessage().contains(NamedStubDao.class.getName()));
assertTrue(expected.getMessage().contains(NamedStubDao2.class.getName()));
}
}
@Test
public void testCustomIncludeFilterWithoutDefaultsButIncludingPostProcessors() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false);
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(4, beanCount);
assertTrue(context.containsBean("messageBean"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomIncludeFilterWithoutDefaultsAndNoPostProcessors() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false);
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(4, beanCount);
assertTrue(context.containsBean("messageBean"));
assertFalse(context.containsBean("serviceInvocationCounter"));
assertFalse(context.containsBean("fooServiceImpl"));
assertFalse(context.containsBean("stubFooDao"));
assertFalse(context.containsBean("myNamedComponent"));
assertFalse(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomIncludeFilterAndDefaults() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(10, beanCount);
assertTrue(context.containsBean("messageBean"));
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomAnnotationExcludeFilterAndDefaults() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(8, beanCount);
assertFalse(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomAssignableTypeExcludeFilterAndDefaults() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(8, beanCount);
assertFalse(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomAssignableTypeExcludeFilterAndDefaultsWithoutPostProcessors() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.setIncludeAnnotationConfig(false);
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(5, beanCount);
assertFalse(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertFalse(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertFalse(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertFalse(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testMultipleCustomExcludeFiltersAndDefaults() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(7, beanCount);
assertFalse(context.containsBean("fooServiceImpl"));
assertFalse(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testCustomBeanNameGenerator() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(9, beanCount);
assertFalse(context.containsBean("fooServiceImpl"));
assertTrue(context.containsBean("fooService"));
assertTrue(context.containsBean("serviceInvocationCounter"));
assertTrue(context.containsBean("stubFooDao"));
assertTrue(context.containsBean("myNamedComponent"));
assertTrue(context.containsBean("myNamedDao"));
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
@Test
public void testMultipleBasePackagesWithDefaultsOnly() {
GenericApplicationContext singlePackageContext = new GenericApplicationContext();
ClassPathBeanDefinitionScanner singlePackageScanner = new ClassPathBeanDefinitionScanner(singlePackageContext);
GenericApplicationContext multiPackageContext = new GenericApplicationContext();
ClassPathBeanDefinitionScanner multiPackageScanner = new ClassPathBeanDefinitionScanner(multiPackageContext);
int singlePackageBeanCount = singlePackageScanner.scan(BASE_PACKAGE);
assertEquals(9, singlePackageBeanCount);
multiPackageScanner.scan(BASE_PACKAGE, "org.springframework.dao.annotation");
// assertTrue(multiPackageBeanCount > singlePackageBeanCount);
}
@Test
public void testMultipleScanCalls() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(9, beanCount);
assertEquals(beanCount, context.getBeanDefinitionCount());
int addedBeanCount = scanner.scan("org.springframework.aop.aspectj.annotation");
assertEquals(beanCount + addedBeanCount, context.getBeanDefinitionCount());
}
@Test
public void testBeanAutowiredWithAnnotationConfigEnabled() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("myBf", new RootBeanDefinition(StaticListableBeanFactory.class));
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(9, beanCount);
context.refresh();
FooServiceImpl fooService = (FooServiceImpl) context.getBean("fooService");
StaticListableBeanFactory myBf = (StaticListableBeanFactory) context.getBean("myBf");
MessageSource ms = (MessageSource) context.getBean("messageSource");
assertTrue(fooService.isInitCalled());
assertEquals("bar", fooService.foo(123));
assertSame(context.getDefaultListableBeanFactory(), fooService.beanFactory);
assertEquals(2, fooService.listableBeanFactory.size());
assertSame(context.getDefaultListableBeanFactory(), fooService.listableBeanFactory.get(0));
assertSame(myBf, fooService.listableBeanFactory.get(1));
assertSame(context, fooService.resourceLoader);
assertSame(context, fooService.resourcePatternResolver);
assertSame(context, fooService.eventPublisher);
assertSame(ms, fooService.messageSource);
assertSame(context, fooService.context);
assertEquals(1, fooService.configurableContext.length);
assertSame(context, fooService.configurableContext[0]);
assertSame(context, fooService.genericContext);
}
@Test
public void testBeanNotAutowiredWithAnnotationConfigDisabled() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
int beanCount = scanner.scan(BASE_PACKAGE);
assertEquals(6, beanCount);
context.refresh();
FooService fooService = (FooService) context.getBean("fooService");
assertFalse(fooService.isInitCalled());
try {
fooService.foo(123);
fail("NullPointerException expected; fooDao must not have been set");
}
catch (NullPointerException expected) {
}
}
@Test
public void testAutowireCandidatePatternMatches() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(true);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
scanner.setAutowireCandidatePatterns(new String[] { "*FooDao" });
scanner.scan(BASE_PACKAGE);
context.refresh();
FooService fooService = (FooService) context.getBean("fooService");
assertEquals("bar", fooService.foo(123));
}
@Test
public void testAutowireCandidatePatternDoesNotMatch() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(true);
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
scanner.setAutowireCandidatePatterns(new String[] { "*NoSuchDao" });
scanner.scan(BASE_PACKAGE);
try {
context.refresh();
fail("BeanCreationException expected; fooDao should not have been an autowire-candidate");
}
catch (BeanCreationException expected) {
assertTrue(expected.getMostSpecificCause() instanceof NoSuchBeanDefinitionException);
}
}
private static class TestBeanNameGenerator extends AnnotationBeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
String beanName = super.generateBeanName(definition, registry);
return beanName.replace("Impl", "");
}
}
@Component("toBeIgnored")
public class NonStaticInnerClass {
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
/**
* @author Juergen Hoeller
* @author Chris Beams
*/
public class DoubleScanTests extends SimpleScanTests {
@Override
protected String[] getConfigLocations() {
return new String[] {"doubleScanTests.xml"};
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import example.scannable.FooService;
import example.scannable.ServiceInvocationCounter;
/**
* @author Mark Fisher
*/
public class SimpleConfigTests {
@Test
public void testFooService() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(getConfigLocations(), getClass());
FooService fooService = (FooService) ctx.getBean("fooServiceImpl");
ServiceInvocationCounter serviceInvocationCounter = (ServiceInvocationCounter) ctx.getBean("serviceInvocationCounter");
String value = fooService.foo(1);
assertEquals("bar", value);
assertEquals(1, serviceInvocationCounter.getCount());
fooService.foo(1);
assertEquals(2, serviceInvocationCounter.getCount());
}
public String[] getConfigLocations() {
return new String[] {"simpleConfigTests.xml"};
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import example.scannable.FooService;
import example.scannable.ServiceInvocationCounter;
/**
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
*/
public class SimpleScanTests {
protected String[] getConfigLocations() {
return new String[] {"simpleScanTests.xml"};
}
@Test
public void testFooService() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(getConfigLocations(), getClass());
FooService fooService = (FooService) ctx.getBean("fooServiceImpl");
ServiceInvocationCounter serviceInvocationCounter = (ServiceInvocationCounter) ctx.getBean("serviceInvocationCounter");
assertEquals(0, serviceInvocationCounter.getCount());
assertTrue(fooService.isInitCalled());
assertEquals(1, serviceInvocationCounter.getCount());
String value = fooService.foo(1);
assertEquals("bar", value);
assertEquals(2, serviceInvocationCounter.getCount());
fooService.foo(1);
assertEquals(3, serviceInvocationCounter.getCount());
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="example.scannable"/>
<!-- shouldn't cause a conflict -->
<context:component-scan base-package="example.scannable"/>
<aop:aspectj-autoproxy/>
</beans>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<aop:aspectj-autoproxy/>
<bean id="fooServiceImpl" class="example.scannable.FooServiceImpl"/>
<bean id="serviceInvocationCounter" class="example.scannable.ServiceInvocationCounter"/>
<bean class="example.scannable.StubFooDao"/>
</beans>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="example.scannable"/>
<aop:aspectj-autoproxy/>
</beans>

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation2;
import org.springframework.stereotype.Repository;
/**
* @author Juergen Hoeller
*/
@Repository("myNamedDao")
public class NamedStubDao2 {
public String find(int id) {
return "bar";
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation3;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import example.scannable.FooDao;
/**
* @author Mark Fisher
*/
@Repository
@Qualifier("testing")
public class StubFooDao implements FooDao {
public String findFoo(int id) {
return "bar";
}
}