From 8fcce02cde1c0114706b565727ca14fc201b083f Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Wed, 9 Feb 2011 06:54:02 +0000 Subject: [PATCH] Add FeatureMethodErrorTests Capture common mistakes with @Feature method declarations and ensure that useful error messages are produced. git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3966 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../ConfigurationClassPostProcessor.java | 3 +- .../annotation/FeatureMethodErrorTests.java | 113 ++++++++++++++++++ .../context/annotation/FeatureTestSuite.java | 25 ++-- 3 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 org.springframework.context/src/test/java/org/springframework/context/annotation/FeatureMethodErrorTests.java diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 8425a537c94..30a73a78b08 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -322,7 +322,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo if (!(FeatureSpecification.class.isAssignableFrom(featureMethod.getReturnType()))) { // TODO SPR-7420: raise a Problem instead? throw new IllegalArgumentException( - "return type from @Feature methods must be assignable to FeatureSpecification"); + format("Return type for @Feature method %s.%s() must be assignable to FeatureSpecification", + featureMethod.getDeclaringClass().getSimpleName(), featureMethod.getName())); } List beanArgs = new ArrayList(); diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/FeatureMethodErrorTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/FeatureMethodErrorTests.java new file mode 100644 index 00000000000..10566d58918 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/FeatureMethodErrorTests.java @@ -0,0 +1,113 @@ +/* + * Copyright 2002-2011 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.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.context.annotation.configuration.StubSpecification; +import org.springframework.context.config.FeatureSpecification; + +import test.beans.TestBean; + +/** + * Tests proving that @Feature methods may reference the product of @Bean methods. + * + * @author Chris Beams + * @since 3.1 + */ +public class FeatureMethodErrorTests { + + @Test + public void incorrectReturnType() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(FeatureConfig.class); + try { + ctx.refresh(); + fail("expected exception"); + } catch (FeatureMethodExecutionException ex) { + assertThat(ex.getCause().getMessage(), + equalTo("Return type for @Feature method FeatureConfig.f() must be " + + "assignable to FeatureSpecification")); + } + } + + @Test + public void voidReturnType() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(VoidFeatureConfig.class); + try { + ctx.refresh(); + fail("expected exception"); + } catch (FeatureMethodExecutionException ex) { + assertThat(ex.getCause().getMessage(), + equalTo("Return type for @Feature method VoidFeatureConfig.f() must be " + + "assignable to FeatureSpecification")); + } + } + + @Test + public void containsBeanMethod() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(FeatureConfigWithBeanMethod.class); + try { + ctx.refresh(); + fail("expected exception"); + } catch (FeatureMethodExecutionException ex) { + assertThat(ex.getMessage(), + equalTo("@FeatureConfiguration classes must not contain @Bean-annotated methods. " + + "FeatureConfigWithBeanMethod.testBean() is annotated with @Bean and must " + + "be removed in order to proceed. Consider moving this method into a dedicated " + + "@Configuration class and injecting the bean as a parameter into any @Feature " + + "method(s) that need it.")); + } + } + + + @FeatureConfiguration + static class FeatureConfig { + @Feature + public Object f() { + return new StubSpecification(); + } + } + + + @FeatureConfiguration + static class VoidFeatureConfig { + @Feature + public void f() { + } + } + + + @FeatureConfiguration + static class FeatureConfigWithBeanMethod { + @Feature + public FeatureSpecification f() { + return new StubSpecification(); + } + + @Bean + public TestBean testBean() { + return new TestBean(); + } + } + +} diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/context/annotation/FeatureTestSuite.java b/org.springframework.integration-tests/src/test/java/org/springframework/context/annotation/FeatureTestSuite.java index 51bed0fac12..feb52c6196a 100644 --- a/org.springframework.integration-tests/src/test/java/org/springframework/context/annotation/FeatureTestSuite.java +++ b/org.springframework.integration-tests/src/test/java/org/springframework/context/annotation/FeatureTestSuite.java @@ -16,20 +16,31 @@ package org.springframework.context.annotation; - /** * Tests directly or indirectly related to {@link FeatureConfiguration} class and * {@link Feature} method processing. * * @author Chris Beams * @since 3.1 - */ -/* + * * commented due to classpath visibility differences between Eclipse * and Ant/Ivy at the command line. Eclipse can see classes across * project test folders, Ant/Ivy are not configured to do so. Uncomment * as necessary when doing @Feature-related work. - * +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; +import org.springframework.transaction.TxNamespaceHandlerTests; +import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests; +import org.springframework.transaction.annotation.TxAnnotationDrivenFeatureTests; +import org.springframework.transaction.config.AnnotationDrivenTests; +import org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParserTests; +import org.springframework.web.servlet.config.MvcAnnotationDrivenFeatureTests; +import org.springframework.web.servlet.config.MvcDefaultServletHandlerTests; +import org.springframework.web.servlet.config.MvcNamespaceTests; +import org.springframework.web.servlet.config.MvcResourcesTests; +import org.springframework.web.servlet.config.MvcViewControllersTests; + @RunWith(Suite.class) @SuiteClasses({ EarlyBeanReferenceProxyCreatorTests.class, @@ -37,6 +48,7 @@ package org.springframework.context.annotation; BeanFactoryAwareFeatureConfigurationTests.class, FeatureMethodBeanReferenceTests.class, FeatureMethodQualifiedBeanReferenceTests.class, + FeatureMethodErrorTests.class, FeatureConfigurationClassTests.class, FeatureMethodEarlyBeanProxyTests.class, FeatureConfigurationImportTests.class, @@ -60,9 +72,8 @@ package org.springframework.context.annotation; MvcViewControllersTests.class, MvcResourcesTests.class, MvcDefaultServletHandlerTests.class, - MvcNamespaceTests.class, -}) - */ + MvcNamespaceTests.class +*/ public class FeatureTestSuite { } \ No newline at end of file