+ Added unit test for BeanMethod

master
Chris Beams 16 years ago
parent 72fae2ea19
commit 2bbc4e48ad
  1. 25
      org.springframework.config.java/src/main/java/org/springframework/config/java/support/BeanMethod.java
  2. 2
      org.springframework.config.java/src/main/java/org/springframework/config/java/support/ModelClass.java
  3. 184
      org.springframework.config.java/src/test/java/org/springframework/config/java/support/BeanMethodTests.java

@ -101,9 +101,7 @@ final class BeanMethod implements BeanMetadataElement {
public <T extends Annotation> T getRequiredAnnotation(Class<T> annoType) {
T anno = getAnnotation(annoType);
if (anno == null)
throw new IllegalStateException(
format("annotation %s not found on %s", annoType.getSimpleName(), this));
Assert.notNull(anno, format("annotation %s not found on %s", annoType.getSimpleName(), this));
return anno;
}
@ -130,6 +128,9 @@ final class BeanMethod implements BeanMetadataElement {
}
public Location getLocation() {
if (declaringClass == null)
throw new IllegalStateException(
"declaringClass property is null. Call setDeclaringClass() before calling getLocation()");
return new Location(declaringClass.getLocation().getResource(), getSource());
}
@ -196,24 +197,24 @@ final class BeanMethod implements BeanMetadataElement {
}
/** {@link Bean} methods must be non-private in order to accommodate CGLIB. */
public class PrivateMethodError extends Problem {
public PrivateMethodError() {
super(format("method '%s' may not be private", getName()),
class PrivateMethodError extends Problem {
PrivateMethodError() {
super(format("Method '%s' may not be private; increase the method's visibility to continue", getName()),
BeanMethod.this.getLocation());
}
}
/** {@link Bean} methods must be non-final in order to accommodate CGLIB. */
public class FinalMethodError extends Problem {
public FinalMethodError() {
super(format("method '%s' may not be final. remove the final modifier to continue", getName()),
class FinalMethodError extends Problem {
FinalMethodError() {
super(format("Method '%s' may not be final; remove the final modifier to continue", getName()),
BeanMethod.this.getLocation());
}
}
public class InvalidScopedProxyDeclarationError extends Problem {
public InvalidScopedProxyDeclarationError(BeanMethod method) {
super(format("method %s contains an invalid annotation declaration: scoped proxies "
class InvalidScopedProxyDeclarationError extends Problem {
InvalidScopedProxyDeclarationError(BeanMethod method) {
super(format("Method %s contains an invalid annotation declaration: scoped proxies "
+ "cannot be created for singleton/prototype beans", method.getName()),
BeanMethod.this.getLocation());
}

@ -117,6 +117,8 @@ class ModelClass implements BeanMetadataElement {
}
public Location getLocation() {
if(getName() == null)
throw new IllegalStateException("'name' property is null. Call setName() before calling getLocation()");
return new Location(new ClassPathResource(convertClassNameToResourcePath(getName())), getSource());
}

@ -0,0 +1,184 @@
/*
* Copyright 2002-2009 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.config.java.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.config.java.StandardScopes.*;
import static org.springframework.config.java.support.MutableAnnotationUtils.*;
import static org.springframework.context.annotation.ScopedProxyMode.*;
import java.lang.reflect.Modifier;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.config.java.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.ClassPathResource;
/**
* Unit tests for {@link BeanMethod}.
*
* @author Chris Beams
*/
public class BeanMethodTests {
private ProblemReporter problemReporter = new FailFastProblemReporter();
private String beanName = "foo";
private Bean beanAnno = createMutableAnnotation(Bean.class);
private ModelClass returnType = new ModelClass("FooType");
private ConfigurationClass declaringClass = new ConfigurationClass();
{ declaringClass.setName("test.Config"); }
@Test
public void testWellFormedMethod() {
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno);
assertThat(beanMethod.getName(), sameInstance(beanName));
assertThat(beanMethod.getModifiers(), equalTo(0));
assertThat(beanMethod.getReturnType(), sameInstance(returnType));
assertThat(beanMethod.getAnnotation(Bean.class), sameInstance(beanAnno));
assertThat(beanMethod.getAnnotation(Override.class), nullValue());
assertThat(beanMethod.getRequiredAnnotation(Bean.class), sameInstance(beanAnno));
try {
beanMethod.getRequiredAnnotation(Override.class);
fail("expected IllegalArgumentException ex");
} catch (IllegalArgumentException ex) { /* expected */ }
// must call setDeclaringClass() before calling getLocation()
try {
beanMethod.getLocation();
fail("expected IllegalStateException ex");
} catch (IllegalStateException ex) { /* expected */ }
beanMethod.setDeclaringClass(declaringClass);
assertThat(beanMethod.getDeclaringClass(), sameInstance(declaringClass));
beanMethod.setSource(12); // indicating a line number
assertEquals(beanMethod.getSource(), 12);
Location location = beanMethod.getLocation();
assertEquals(location.getResource(), new ClassPathResource("test/Config"));
assertEquals(location.getSource(), 12);
// should validate without throwing as this is a well-formed method
beanMethod.validate(problemReporter);
}
@Test
public void finalMethodsAreIllegal() {
BeanMethod beanMethod = new BeanMethod(beanName, Modifier.FINAL, returnType, beanAnno);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to final bean method");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage().contains("remove the final modifier"));
}
}
@Test
public void privateMethodsAreIllegal() {
BeanMethod beanMethod = new BeanMethod(beanName, Modifier.PRIVATE, returnType, beanAnno);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to private bean method");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage().contains("increase the method's visibility"));
}
}
@Test
public void singletonInterfaceScopedProxiesAreIllegal() {
Scope scope = SingletonInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to singleton with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void singletonTargetClassScopedProxiesAreIllegal() {
Scope scope = SingletonTargetClassProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to singleton with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void singletonsSansProxyAreLegal() {
Scope scope = SingletonNoProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
beanMethod.validate(problemReporter); // should validate without problems - it's legal
}
@Test
public void prototypeInterfaceScopedProxiesAreIllegal() {
Scope scope = PrototypeInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to prototype with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void sessionInterfaceScopedProxiesAreLegal() {
Scope scope = PrototypeInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to prototype with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Scope(value=SINGLETON, proxyMode=INTERFACES)
private class SingletonInterfaceProxy { }
@Scope(value=SINGLETON, proxyMode=TARGET_CLASS)
private class SingletonTargetClassProxy { }
@Scope(value=SINGLETON, proxyMode=NO)
private class SingletonNoProxy { }
@Scope(value=PROTOTYPE, proxyMode=INTERFACES)
private class PrototypeInterfaceProxy { }
@Scope(value=SESSION, proxyMode=INTERFACES)
private class SessionInterfaceProxy { }
}
Loading…
Cancel
Save