diff options
Diffstat (limited to 'spring-test/src/test/java/org/springframework')
106 files changed, 3805 insertions, 807 deletions
diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockFilterChainTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockFilterChainTests.java index bbafd498..d008751f 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockFilterChainTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockFilterChainTests.java @@ -83,7 +83,7 @@ public class MockFilterChainTests { chain.doFilter(this.request, this.response); fail("Expected Exception"); } - catch(IllegalStateException ex) { + catch (IllegalStateException ex) { assertEquals("This FilterChain has already been called!", ex.getMessage()); } } @@ -98,7 +98,7 @@ public class MockFilterChainTests { chain.doFilter(this.request, this.response); fail("Expected Exception"); } - catch(IllegalStateException ex) { + catch (IllegalStateException ex) { assertEquals("This FilterChain has already been called!", ex.getMessage()); } } @@ -122,7 +122,7 @@ public class MockFilterChainTests { chain.doFilter(this.request, this.response); fail("Expected Exception"); } - catch(IllegalStateException ex) { + catch (IllegalStateException ex) { assertEquals("This FilterChain has already been called!", ex.getMessage()); } } diff --git a/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java b/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java index 4296fd07..da461bee 100644 --- a/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -91,7 +91,10 @@ public class ProfileValueUtilsTests { assertClassIsEnabled(EnabledAnnotatedMultiValue.class); assertClassIsEnabled(MetaEnabledClass.class); assertClassIsEnabled(MetaEnabledWithCustomProfileValueSourceClass.class); + assertClassIsEnabled(EnabledWithCustomProfileValueSourceOnTestInterface.class); + assertClassIsDisabled(DisabledAnnotatedSingleValue.class); + assertClassIsDisabled(DisabledAnnotatedSingleValueOnTestInterface.class); assertClassIsDisabled(DisabledAnnotatedMultiValue.class); assertClassIsDisabled(MetaDisabledClass.class); assertClassIsDisabled(MetaDisabledWithCustomProfileValueSourceClass.class); @@ -105,6 +108,7 @@ public class ProfileValueUtilsTests { assertMethodIsEnabled(ENABLED_ANNOTATED_METHOD, EnabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, EnabledAnnotatedSingleValue.class); + assertMethodIsEnabled(NON_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); assertMethodIsEnabled(ENABLED_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); @@ -117,6 +121,8 @@ public class ProfileValueUtilsTests { assertMethodIsDisabled(ENABLED_ANNOTATED_METHOD, DisabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, DisabledAnnotatedSingleValue.class); + assertMethodIsDisabled(NON_ANNOTATED_METHOD, DisabledAnnotatedSingleValueOnTestInterface.class); + assertMethodIsDisabled(NON_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); assertMethodIsDisabled(ENABLED_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); @@ -176,6 +182,17 @@ public class ProfileValueUtilsTests { } } + @IfProfileValue(name = NAME, value = VALUE + "X") + private interface IfProfileValueTestInterface { + } + + @SuppressWarnings("unused") + private static class DisabledAnnotatedSingleValueOnTestInterface implements IfProfileValueTestInterface { + + public void nonAnnotatedMethod() { + } + } + @SuppressWarnings("unused") @IfProfileValue(name = NAME, values = { "foo", VALUE, "bar" }) private static class EnabledAnnotatedMultiValue { @@ -302,4 +319,13 @@ public class ProfileValueUtilsTests { private static class MetaDisabledWithCustomProfileValueSourceClass { } + @ProfileValueSourceConfiguration(HardCodedProfileValueSource.class) + private interface CustomProfileValueSourceTestInterface { + } + + @IfProfileValue(name = NAME, value = "42") + private static class EnabledWithCustomProfileValueSourceOnTestInterface + implements CustomProfileValueSourceTestInterface { + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java b/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java index 8efb56d3..70d80ee3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -24,16 +24,20 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.test.context.support.DefaultTestContextBootstrapper; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.context.web.WebTestContextBootstrapper; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; -import static org.springframework.test.context.BootstrapUtils.*; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper; /** * Unit tests for {@link BootstrapUtils}. * * @author Sam Brannen + * @author Phillip Webb * @since 4.2 */ public class BootstrapUtilsTests { @@ -41,7 +45,7 @@ public class BootstrapUtilsTests { private final CacheAwareContextLoaderDelegate delegate = mock(CacheAwareContextLoaderDelegate.class); @Rule - public ExpectedException exception = ExpectedException.none(); + public final ExpectedException exception = ExpectedException.none(); @Test public void resolveTestContextBootstrapperForNonAnnotatedClass() { @@ -49,6 +53,11 @@ public class BootstrapUtilsTests { } @Test + public void resolveTestContextBootstrapperForWebAppConfigurationAnnotatedClass() { + assertBootstrapper(WebAppConfigurationAnnotatedClass.class, WebTestContextBootstrapper.class); + } + + @Test public void resolveTestContextBootstrapperWithEmptyBootstrapWithAnnotation() { BootstrapContext bootstrapContext = BootstrapTestUtils.buildBootstrapContext(EmptyBootstrapWithAnnotationClass.class, delegate); @@ -124,4 +133,7 @@ public class BootstrapUtilsTests { @BootWithFoo static class DoubleMetaAnnotatedBootstrapWithAnnotationClass {} + @WebAppConfiguration + static class WebAppConfigurationAnnotatedClass {} + } diff --git a/spring-test/src/test/java/org/springframework/test/context/MergedContextConfigurationTests.java b/spring-test/src/test/java/org/springframework/test/context/MergedContextConfigurationTests.java index bf8eba04..0409e11f 100644 --- a/spring-test/src/test/java/org/springframework/test/context/MergedContextConfigurationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/MergedContextConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -16,6 +16,7 @@ package org.springframework.test.context; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -28,6 +29,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; import org.springframework.test.context.support.GenericXmlContextLoader; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; /** * Unit tests for {@link MergedContextConfiguration}. @@ -37,6 +39,7 @@ import static org.junit.Assert.*; * {@link org.springframework.test.context.cache.ContextCache ContextCache}. * * @author Sam Brannen + * @author Phillip Webb * @since 3.1 */ public class MergedContextConfigurationTests { @@ -401,6 +404,35 @@ public class MergedContextConfigurationTests { } /** + * @since 4.3 + */ + @Test + public void equalsWithSameContextCustomizers() { + Set<ContextCustomizer> customizers = Collections.singleton(mock(ContextCustomizer.class)); + MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY, + EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers, loader, null, null); + MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY, + EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers, loader, null, null); + assertEquals(mergedConfig1, mergedConfig2); + } + + /** + * @since 4.3 + */ + @Test + public void equalsWithDifferentContextCustomizers() { + Set<ContextCustomizer> customizers1 = Collections.singleton(mock(ContextCustomizer.class)); + Set<ContextCustomizer> customizers2 = Collections.singleton(mock(ContextCustomizer.class)); + + MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY, + EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers1, loader, null, null); + MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY, + EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, null, null, customizers2, loader, null, null); + assertNotEquals(mergedConfig1, mergedConfig2); + assertNotEquals(mergedConfig2, mergedConfig1); + } + + /** * @since 3.2.2 */ @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java index 648655fb..4df53d82 100644 --- a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java @@ -116,6 +116,12 @@ public class TestExecutionListenersTests { } @Test + public void customListenersDeclaredOnInterface() { + assertRegisteredListeners(ExplicitListenersOnTestInterfaceTestCase.class, + asList(FooTestExecutionListener.class, BarTestExecutionListener.class)); + } + + @Test public void nonInheritedListeners() { assertNumRegisteredListeners(NonInheritedListenersTestCase.class, 1); } @@ -229,6 +235,13 @@ public class TestExecutionListenersTests { static class NonInheritedListenersTestCase extends InheritedListenersTestCase { } + @TestExecutionListeners({ FooTestExecutionListener.class, BarTestExecutionListener.class }) + interface ExplicitListenersTestInterface { + } + + static class ExplicitListenersOnTestInterfaceTestCase implements ExplicitListenersTestInterface { + } + @TestExecutionListeners(listeners = FooTestExecutionListener.class, value = BarTestExecutionListener.class) static class DuplicateListenersConfigTestCase { } diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTestNGTests.java index 2fcbdb46..1c603e33 100644 --- a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTestNGTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTestNGTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -171,7 +171,7 @@ public class ClassLevelDirtiesContextTestNGTests { @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }, inheritListeners = false) @ContextConfiguration - public static abstract class BaseTestCase extends AbstractTestNGSpringContextTests { + static abstract class BaseTestCase extends AbstractTestNGSpringContextTests { @Configuration static class Config { @@ -189,75 +189,75 @@ public class ClassLevelDirtiesContextTestNGTests { } } - public static final class CleanTestCase extends BaseTestCase { + static final class CleanTestCase extends BaseTestCase { @org.testng.annotations.Test - public void verifyContextWasAutowired() { + void verifyContextWasAutowired() { assertApplicationContextWasAutowired(); } } @DirtiesContext - public static class ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends BaseTestCase { + static class ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends BaseTestCase { @org.testng.annotations.Test - public void verifyContextWasAutowired() { + void verifyContextWasAutowired() { assertApplicationContextWasAutowired(); } } - public static class InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends + static class InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase { } @DirtiesContext(classMode = ClassMode.AFTER_CLASS) - public static class ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends BaseTestCase { + static class ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends BaseTestCase { @org.testng.annotations.Test - public void verifyContextWasAutowired() { + void verifyContextWasAutowired() { assertApplicationContextWasAutowired(); } } - public static class InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends + static class InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase { } @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) - public static class ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends BaseTestCase { + static class ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends BaseTestCase { @org.testng.annotations.Test - public void verifyContextWasAutowired1() { + void verifyContextWasAutowired1() { assertApplicationContextWasAutowired(); } @org.testng.annotations.Test - public void verifyContextWasAutowired2() { + void verifyContextWasAutowired2() { assertApplicationContextWasAutowired(); } @org.testng.annotations.Test - public void verifyContextWasAutowired3() { + void verifyContextWasAutowired3() { assertApplicationContextWasAutowired(); } } - public static class InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends + static class InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase { } @DirtiesContext - public static class ClassLevelDirtiesContextWithDirtyMethodsTestCase extends BaseTestCase { + static class ClassLevelDirtiesContextWithDirtyMethodsTestCase extends BaseTestCase { @org.testng.annotations.Test @DirtiesContext - public void dirtyContext() { + void dirtyContext() { assertApplicationContextWasAutowired(); } } - public static class InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase extends + static class InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase extends ClassLevelDirtiesContextWithDirtyMethodsTestCase { } diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java index 896c4654..9da13e7b 100644 --- a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -30,10 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; -import org.springframework.test.context.support.DirtiesContextTestExecutionListener; +import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.*; import static org.springframework.test.context.cache.ContextCacheTestUtils.*; @@ -41,9 +38,8 @@ import static org.springframework.test.context.junit4.JUnitTestingUtils.*; /** * JUnit 4 based integration test which verifies correct {@linkplain ContextCache - * application context caching} in conjunction with the - * {@link SpringJUnit4ClassRunner} and {@link DirtiesContext @DirtiesContext} - * at the class level. + * application context caching} in conjunction with the {@link SpringRunner} and + * {@link DirtiesContext @DirtiesContext} at the class level. * * @author Sam Brannen * @since 3.0 @@ -148,10 +144,9 @@ public class ClassLevelDirtiesContextTests { // ------------------------------------------------------------------- - @RunWith(SpringJUnit4ClassRunner.class) - @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) + @RunWith(SpringRunner.class) @ContextConfiguration - public static abstract class BaseTestCase { + static abstract class BaseTestCase { @Configuration static class Config { diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheTests.java index 5d518d3c..4624fcb7 100644 --- a/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -42,6 +42,7 @@ import static org.springframework.test.context.cache.ContextCacheTestUtils.*; * @author Sam Brannen * @author Michail Nikolaev * @since 3.1 + * @see LruContextCacheTests * @see SpringRunnerContextCacheTests */ public class ContextCacheTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheUtilsTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheUtilsTests.java new file mode 100644 index 00000000..ac6cc723 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/cache/ContextCacheUtilsTests.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2016 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.test.context.cache; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.core.SpringProperties; + +import static org.junit.Assert.*; +import static org.springframework.test.context.cache.ContextCacheUtils.*; +import static org.springframework.test.context.cache.ContextCache.*; + +/** + * Unit tests for {@link ContextCacheUtils}. + * + * @author Sam Brannen + * @since 4.3 + */ +public class ContextCacheUtilsTests { + + @Before + @After + public void clearProperties() { + System.clearProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME); + SpringProperties.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, null); + } + + @Test + public void retrieveMaxCacheSizeFromDefault() { + assertDefaultValue(); + } + + @Test + public void retrieveMaxCacheSizeFromBogusSystemProperty() { + System.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "bogus"); + assertDefaultValue(); + } + + @Test + public void retrieveMaxCacheSizeFromBogusSpringProperty() { + SpringProperties.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "bogus"); + assertDefaultValue(); + } + + @Test + public void retrieveMaxCacheSizeFromDecimalSpringProperty() { + SpringProperties.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "3.14"); + assertDefaultValue(); + } + + @Test + public void retrieveMaxCacheSizeFromSystemProperty() { + System.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "42"); + assertEquals(42, retrieveMaxCacheSize()); + } + + @Test + public void retrieveMaxCacheSizeFromSystemPropertyContainingWhitespace() { + System.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "42\t"); + assertEquals(42, retrieveMaxCacheSize()); + } + + @Test + public void retrieveMaxCacheSizeFromSpringProperty() { + SpringProperties.setProperty(MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME, "99"); + assertEquals(99, retrieveMaxCacheSize()); + } + + private static void assertDefaultValue() { + assertEquals(DEFAULT_MAX_CONTEXT_CACHE_SIZE, retrieveMaxCacheSize()); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/LruContextCacheTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/LruContextCacheTests.java new file mode 100644 index 00000000..4ae97b61 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/cache/LruContextCacheTests.java @@ -0,0 +1,177 @@ +/* + * Copyright 2002-2016 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.test.context.cache; + +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.util.ReflectionTestUtils; + +import static java.util.Arrays.*; +import static java.util.stream.Collectors.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Unit tests for the LRU eviction policy in {@link DefaultContextCache}. + * + * @author Sam Brannen + * @since 4.3 + * @see ContextCacheTests + */ +public class LruContextCacheTests { + + private static final MergedContextConfiguration abcConfig = config(Abc.class); + private static final MergedContextConfiguration fooConfig = config(Foo.class); + private static final MergedContextConfiguration barConfig = config(Bar.class); + private static final MergedContextConfiguration bazConfig = config(Baz.class); + + + private final ConfigurableApplicationContext abcContext = mock(ConfigurableApplicationContext.class); + private final ConfigurableApplicationContext fooContext = mock(ConfigurableApplicationContext.class); + private final ConfigurableApplicationContext barContext = mock(ConfigurableApplicationContext.class); + private final ConfigurableApplicationContext bazContext = mock(ConfigurableApplicationContext.class); + + + @Test(expected = IllegalArgumentException.class) + public void maxCacheSizeNegativeOne() { + new DefaultContextCache(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void maxCacheSizeZero() { + new DefaultContextCache(0); + } + + @Test + public void maxCacheSizeOne() { + DefaultContextCache cache = new DefaultContextCache(1); + assertEquals(0, cache.size()); + assertEquals(1, cache.getMaxSize()); + + cache.put(fooConfig, fooContext); + assertCacheContents(cache, "Foo"); + + cache.put(fooConfig, fooContext); + assertCacheContents(cache, "Foo"); + + cache.put(barConfig, barContext); + assertCacheContents(cache, "Bar"); + + cache.put(fooConfig, fooContext); + assertCacheContents(cache, "Foo"); + } + + @Test + public void maxCacheSizeThree() { + DefaultContextCache cache = new DefaultContextCache(3); + assertEquals(0, cache.size()); + assertEquals(3, cache.getMaxSize()); + + cache.put(fooConfig, fooContext); + assertCacheContents(cache, "Foo"); + + cache.put(fooConfig, fooContext); + assertCacheContents(cache, "Foo"); + + cache.put(barConfig, barContext); + assertCacheContents(cache, "Foo", "Bar"); + + cache.put(bazConfig, bazContext); + assertCacheContents(cache, "Foo", "Bar", "Baz"); + + cache.put(abcConfig, abcContext); + assertCacheContents(cache, "Bar", "Baz", "Abc"); + } + + @Test + public void ensureLruOrderingIsUpdated() { + DefaultContextCache cache = new DefaultContextCache(3); + + // Note: when a new entry is added it is considered the MRU entry and inserted at the tail. + cache.put(fooConfig, fooContext); + cache.put(barConfig, barContext); + cache.put(bazConfig, bazContext); + assertCacheContents(cache, "Foo", "Bar", "Baz"); + + // Note: the MRU entry is moved to the tail when accessed. + cache.get(fooConfig); + assertCacheContents(cache, "Bar", "Baz", "Foo"); + + cache.get(barConfig); + assertCacheContents(cache, "Baz", "Foo", "Bar"); + + cache.get(bazConfig); + assertCacheContents(cache, "Foo", "Bar", "Baz"); + + cache.get(barConfig); + assertCacheContents(cache, "Foo", "Baz", "Bar"); + } + + @Test + public void ensureEvictedContextsAreClosed() { + DefaultContextCache cache = new DefaultContextCache(2); + + cache.put(fooConfig, fooContext); + cache.put(barConfig, barContext); + assertCacheContents(cache, "Foo", "Bar"); + + cache.put(bazConfig, bazContext); + assertCacheContents(cache, "Bar", "Baz"); + verify(fooContext, times(1)).close(); + + cache.put(abcConfig, abcContext); + assertCacheContents(cache, "Baz", "Abc"); + verify(barContext, times(1)).close(); + + verify(abcContext, never()).close(); + verify(bazContext, never()).close(); + } + + + private static MergedContextConfiguration config(Class<?> clazz) { + return new MergedContextConfiguration(null, null, new Class<?>[] { clazz }, null, null); + } + + @SuppressWarnings("unchecked") + private static void assertCacheContents(DefaultContextCache cache, String... expectedNames) { + + Map<MergedContextConfiguration, ApplicationContext> contextMap = + (Map<MergedContextConfiguration, ApplicationContext>) ReflectionTestUtils.getField(cache, "contextMap"); + + // @formatter:off + List<String> actualNames = contextMap.keySet().stream() + .map(cfg -> cfg.getClasses()[0]) + .map(Class::getSimpleName) + .collect(toList()); + // @formatter:on + + assertEquals(asList(expectedNames), actualNames); + } + + + private static class Abc {} + private static class Foo {} + private static class Bar {} + private static class Baz {} + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/SpringRunnerContextCacheTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/SpringRunnerContextCacheTests.java index 44962e76..bde994dc 100644 --- a/spring-test/src/test/java/org/springframework/test/context/cache/SpringRunnerContextCacheTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/cache/SpringRunnerContextCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -45,6 +45,7 @@ import static org.springframework.test.context.cache.ContextCacheTestUtils.*; * @author Juergen Hoeller * @since 2.5 * @see ContextCacheTests + * @see LruContextCacheTests */ @RunWith(SpringJUnit4ClassRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java new file mode 100644 index 00000000..80d33c8d --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java @@ -0,0 +1,65 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.tests.sample.beans.Employee; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ActiveProfilesInterfaceTests implements ActiveProfilesTestInterface { + + @Autowired + Employee employee; + + + @Test + public void profileFromTestInterface() { + assertNotNull(employee); + assertEquals("dev", employee.getName()); + } + + + @Configuration + static class Config { + + @Bean + @Profile("dev") + Employee employee1() { + return new Employee("dev"); + } + + @Bean + @Profile("prod") + Employee employee2() { + return new Employee("prod"); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java new file mode 100644 index 00000000..63ef2004 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java @@ -0,0 +1,27 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.test.context.ActiveProfiles; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ActiveProfiles("dev") +interface ActiveProfilesTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java new file mode 100644 index 00000000..47e52b9f --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class BootstrapWithInterfaceTests implements BootstrapWithTestInterface { + + @Autowired + String foo; + + + @Test + public void injectedBean() { + assertEquals("foo", foo); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java new file mode 100644 index 00000000..993f3afa --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import java.util.List; + +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; +import org.springframework.test.context.configuration.interfaces.BootstrapWithTestInterface.CustomTestContextBootstrapper; +import org.springframework.test.context.support.DefaultTestContextBootstrapper; + +import static java.util.Collections.*; + +/** + * @author Sam Brannen + * @author Phillip Webb + * @since 4.3 + */ +@BootstrapWith(CustomTestContextBootstrapper.class) +interface BootstrapWithTestInterface { + + static class CustomTestContextBootstrapper extends DefaultTestContextBootstrapper { + + @Override + protected List<ContextCustomizerFactory> getContextCustomizerFactories() { + return singletonList( + (ContextCustomizerFactory) (testClass, configAttributes) -> (ContextCustomizer) (context, + mergedConfig) -> context.getBeanFactory().registerSingleton("foo", "foo")); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java new file mode 100644 index 00000000..4a035e77 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.tests.sample.beans.Employee; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ContextConfigurationInterfaceTests implements ContextConfigurationTestInterface { + + @Autowired + Employee employee; + + + @Test + public void profileFromTestInterface() { + assertNotNull(employee); + assertEquals("Dilbert", employee.getName()); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java new file mode 100644 index 00000000..7eb452fc --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.configuration.interfaces.ContextConfigurationTestInterface.Config; +import org.springframework.tests.sample.beans.Employee; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextConfiguration(classes = Config.class) +interface ContextConfigurationTestInterface { + + static class Config { + + @Bean + Employee employee() { + return new Employee("Dilbert"); + } + } + +}
\ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java new file mode 100644 index 00000000..832c244b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ContextHierarchyInterfaceTests implements ContextHierarchyTestInterface { + + @Autowired + String foo; + + @Autowired + String bar; + + @Autowired + String baz; + + @Autowired + ApplicationContext context; + + + @Test + public void loadContextHierarchy() { + assertNotNull("child ApplicationContext", context); + assertNotNull("parent ApplicationContext", context.getParent()); + assertNull("grandparent ApplicationContext", context.getParent().getParent()); + assertEquals("foo", foo); + assertEquals("bar", bar); + assertEquals("baz-child", baz); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java new file mode 100644 index 00000000..538e2a93 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.ContextHierarchy; +import org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyTests; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextHierarchy({ + @ContextConfiguration(classes = SingleTestClassWithTwoLevelContextHierarchyTests.ParentConfig.class), + @ContextConfiguration(classes = SingleTestClassWithTwoLevelContextHierarchyTests.ChildConfig.class) }) +interface ContextHierarchyTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java new file mode 100644 index 00000000..6b0be0a1 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; +import static org.springframework.test.context.cache.ContextCacheTestUtils.*; +import static org.springframework.test.context.junit4.JUnitTestingUtils.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(JUnit4.class) +public class DirtiesContextInterfaceTests { + + private static final AtomicInteger cacheHits = new AtomicInteger(0); + private static final AtomicInteger cacheMisses = new AtomicInteger(0); + + + @BeforeClass + public static void verifyInitialCacheState() { + resetContextCache(); + // Reset static counters in case tests are run multiple times in a test suite -- + // for example, via JUnit's @Suite. + cacheHits.set(0); + cacheMisses.set(0); + assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get()); + } + + @AfterClass + public static void verifyFinalCacheState() { + assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get()); + } + + @Test + public void verifyDirtiesContextBehavior() throws Exception { + runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1); + assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode", + 0, cacheHits.get(), cacheMisses.incrementAndGet()); + } + + private void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) throws Exception { + runTestsAndAssertCounters(testClass, expectedTestCount, 0, expectedTestCount, 0, 0); + } + + + @RunWith(SpringRunner.class) + public static class ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase + implements DirtiesContextTestInterface { + + @Autowired + ApplicationContext applicationContext; + + + @Test + public void verifyContextWasAutowired() { + assertNotNull("The application context should have been autowired.", this.applicationContext); + } + + + @Configuration + static class Config { + /* no beans */ + } + + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java new file mode 100644 index 00000000..cd486e14 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java @@ -0,0 +1,27 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.test.annotation.DirtiesContext; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@DirtiesContext +interface DirtiesContextTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java new file mode 100644 index 00000000..26f044f8 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; + +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +public class SqlConfigInterfaceTests extends AbstractTransactionalJUnit4SpringContextTests + implements SqlConfigTestInterface { + + @Test + @Sql(scripts = "/org/springframework/test/context/jdbc/schema.sql", // + config = @SqlConfig(separator = ";")) + @Sql("/org/springframework/test/context/jdbc/data-add-users-with-custom-script-syntax.sql") + public void methodLevelScripts() { + assertNumUsers(3); + } + + protected void assertNumUsers(int expected) { + assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java new file mode 100644 index 00000000..a707a4c2 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.jdbc.EmptyDatabaseConfig; +import org.springframework.test.context.jdbc.SqlConfig; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextConfiguration(classes = EmptyDatabaseConfig.class) +@DirtiesContext +@SqlConfig(commentPrefix = "`", blockCommentStartDelimiter = "#$", blockCommentEndDelimiter = "$#", separator = "@@") +interface SqlConfigTestInterface { +}
\ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java new file mode 100644 index 00000000..66dd6057 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class TestPropertySourceInterfaceTests implements TestPropertySourceTestInterface { + + @Autowired + Environment env; + + + @Test + public void propertiesAreAvailableInEnvironment() { + assertThat(property("foo"), is("bar")); + assertThat(property("enigma"), is("42")); + } + + private String property(String key) { + return env.getProperty(key); + } + + + @Configuration + static class Config { + /* no user beans required for these tests */ + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java new file mode 100644 index 00000000..af27989e --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java @@ -0,0 +1,27 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.test.context.TestPropertySource; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@TestPropertySource(properties = { "foo = bar", "enigma: 42" }) +interface TestPropertySourceTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java new file mode 100644 index 00000000..fdb6706b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class WebAppConfigurationInterfaceTests implements WebAppConfigurationTestInterface { + + @Autowired + WebApplicationContext wac; + + + @Test + public void wacLoaded() { + assertNotNull(wac); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java new file mode 100644 index 00000000..dcfabd14 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2016 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.test.context.configuration.interfaces; + +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.configuration.interfaces.WebAppConfigurationTestInterface.Config; +import org.springframework.test.context.web.WebAppConfiguration; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@WebAppConfiguration +@ContextConfiguration(classes = Config.class) +interface WebAppConfigurationTestInterface { + + @Configuration + static class Config { + /* no user beans required for these tests */ + } + +}
\ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/env/InlinedPropertiesOverridePropertiesFilesTestPropertySourceTests.java b/spring-test/src/test/java/org/springframework/test/context/env/InlinedPropertiesOverridePropertiesFilesTestPropertySourceTests.java new file mode 100644 index 00000000..c50f7ba6 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/env/InlinedPropertiesOverridePropertiesFilesTestPropertySourceTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2016 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.test.context.env; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.env.Environment; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.*; + +/** + * Integration tests for {@link TestPropertySource @TestPropertySource} support with + * inlined properties that overrides properties files. + * + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@TestPropertySource(locations = "explicit.properties", properties = "explicit = inlined") +public class InlinedPropertiesOverridePropertiesFilesTestPropertySourceTests { + + @Autowired + Environment env; + + @Value("${explicit}") + String explicit; + + + @Test + public void inlinedPropertyOverridesValueFromPropertiesFile() { + assertEquals("inlined", env.getProperty("explicit")); + assertEquals("inlined", this.explicit); + } + + + @Configuration + static class Config { + + @Bean + public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java b/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java index 2868b694..f8ba83fd 100644 --- a/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -40,7 +40,7 @@ import static org.junit.Assert.*; public class SingleTestClassWithTwoLevelContextHierarchyTests { @Configuration - static class ParentConfig { + public static class ParentConfig { @Bean public String foo() { @@ -54,7 +54,7 @@ public class SingleTestClassWithTwoLevelContextHierarchyTests { } @Configuration - static class ChildConfig { + public static class ChildConfig { @Bean public String bar() { diff --git a/spring-test/src/test/java/org/springframework/test/context/jdbc/ComposedAnnotationSqlScriptsTests.java b/spring-test/src/test/java/org/springframework/test/context/jdbc/ComposedAnnotationSqlScriptsTests.java new file mode 100644 index 00000000..0e709739 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/jdbc/ComposedAnnotationSqlScriptsTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2016 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.test.context.jdbc; + +import java.lang.annotation.Retention; + +import org.junit.Test; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.jdbc.Sql.ExecutionPhase; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; + +import static java.lang.annotation.RetentionPolicy.*; +import static org.junit.Assert.*; +import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.*; + +/** + * Integration tests that verify support for using {@link Sql @Sql} as a + * merged, composed annotation. + * + * @author Sam Brannen + * @since 4.3 + */ +@ContextConfiguration(classes = EmptyDatabaseConfig.class) +@DirtiesContext +public class ComposedAnnotationSqlScriptsTests extends AbstractTransactionalJUnit4SpringContextTests { + + @Test + @ComposedSql( + scripts = { "drop-schema.sql", "schema.sql" }, + statements = "INSERT INTO user VALUES('Dilbert')", + executionPhase = BEFORE_TEST_METHOD + ) + public void composedSqlAnnotation() { + assertEquals("Number of rows in the 'user' table.", 1, countRowsInTable("user")); + } + + + @Sql + @Retention(RUNTIME) + @interface ComposedSql { + + @AliasFor(annotation = Sql.class) + String[] value() default {}; + + @AliasFor(annotation = Sql.class) + String[] scripts() default {}; + + @AliasFor(annotation = Sql.class) + String[] statements() default {}; + + @AliasFor(annotation = Sql.class) + ExecutionPhase executionPhase(); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/jdbc/MetaAnnotationSqlScriptsTests.java b/spring-test/src/test/java/org/springframework/test/context/jdbc/MetaAnnotationSqlScriptsTests.java index 3417c17f..4fc2069e 100644 --- a/spring-test/src/test/java/org/springframework/test/context/jdbc/MetaAnnotationSqlScriptsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/jdbc/MetaAnnotationSqlScriptsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -31,7 +31,7 @@ import static org.junit.Assert.*; /** * Integration tests that verify support for using {@link Sql @Sql} and - * {@link SqlGroup @SqlGroup} as a meta-annotations. + * {@link SqlGroup @SqlGroup} as meta-annotations. * * @author Sam Brannen * @since 4.1 diff --git a/spring-test/src/test/java/org/springframework/test/context/jdbc/PrimaryDataSourceTests.java b/spring-test/src/test/java/org/springframework/test/context/jdbc/PrimaryDataSourceTests.java new file mode 100644 index 00000000..f0716780 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/jdbc/PrimaryDataSourceTests.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2016 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.test.context.jdbc; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; +import org.springframework.test.transaction.TransactionTestUtils; + +import static org.junit.Assert.*; + +/** + * Integration tests that ensure that <em>primary</em> data sources are + * supported. + * + * @author Sam Brannen + * @since 4.3 + * @see org.springframework.test.context.transaction.PrimaryTransactionManagerTests + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@DirtiesContext +public class PrimaryDataSourceTests { + + @Configuration + static class Config { + + @Primary + @Bean + public DataSource primaryDataSource() { + // @formatter:off + return new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .addScript("classpath:/org/springframework/test/context/jdbc/schema.sql") + .build(); + // @formatter:on + } + + @Bean + public DataSource additionalDataSource() { + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); + } + + } + + + private JdbcTemplate jdbcTemplate; + + + @Autowired + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Test + @Sql("data.sql") + public void dataSourceTest() { + TransactionTestUtils.assertInTransaction(false); + assertEquals("Number of rows in the 'user' table.", 1, + JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user")); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/AbstractTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/AbstractTransactionalSpringRunnerTests.java index 493be806..5760755f 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/AbstractTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/AbstractTransactionalSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -32,7 +32,7 @@ import org.springframework.transaction.annotation.Transactional; * @see MethodLevelTransactionalSpringRunnerTests * @see Transactional */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("transactionalTests-context.xml") public abstract class AbstractTransactionalSpringRunnerTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/BeforeAndAfterTransactionAnnotationTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/BeforeAndAfterTransactionAnnotationTests.java index 23440f7d..4596e6cf 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/BeforeAndAfterTransactionAnnotationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/BeforeAndAfterTransactionAnnotationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @@ -43,6 +44,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @author Sam Brannen * @since 2.5 */ +@Transactional public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactionalSpringRunnerTests { protected static JdbcTemplate jdbcTemplate; @@ -79,7 +81,7 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio } @BeforeTransaction - public void beforeTransaction() { + void beforeTransaction() { assertInTransaction(false); this.inTransaction = true; BeforeAndAfterTransactionAnnotationTests.numBeforeTransactionCalls++; @@ -88,7 +90,7 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio } @AfterTransaction - public void afterTransaction() { + void afterTransaction() { assertInTransaction(false); this.inTransaction = false; BeforeAndAfterTransactionAnnotationTests.numAfterTransactionCalls++; @@ -115,7 +117,6 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio } @Test - @Transactional public void transactionalMethod1() { assertInTransaction(true); assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); @@ -124,7 +125,6 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio } @Test - @Transactional public void transactionalMethod2() { assertInTransaction(true); assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); @@ -134,6 +134,7 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio } @Test + @Transactional(propagation = Propagation.NOT_SUPPORTED) public void nonTransactionalMethod() { assertInTransaction(false); assertEquals("Adding luke", 1, addPerson(jdbcTemplate, LUKE)); diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelDisabledSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelDisabledSpringRunnerTests.java index b55abdaa..2db442a9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelDisabledSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelDisabledSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -30,7 +30,7 @@ import static org.junit.Assert.*; * @author Juergen Hoeller * @author Sam Brannen */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @TestExecutionListeners(ClassLevelDisabledSpringRunnerTests.CustomTestExecutionListener.class) @IfProfileValue(name = "ClassLevelDisabledSpringRunnerTests.profile_value.name", value = "enigmaX") public class ClassLevelDisabledSpringRunnerTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelTransactionalSpringRunnerTests.java index 8f29a2d0..5eb8c8ed 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassLevelTransactionalSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -41,7 +41,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * {@link Transactional @Transactional}, {@link TestExecutionListeners * @TestExecutionListeners}, and {@link ContextConfiguration * @ContextConfiguration} annotations in conjunction with the - * {@link SpringJUnit4ClassRunner} and the following + * {@link SpringRunner} and the following * {@link TestExecutionListener TestExecutionListeners}: * * <ul> diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/ContextCustomizerSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/ContextCustomizerSpringRunnerTests.java new file mode 100644 index 00000000..2edfb0d5 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/ContextCustomizerSpringRunnerTests.java @@ -0,0 +1,66 @@ +/* + * Copyright 2002-2016 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.test.context.junit4; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; +import org.springframework.test.context.junit4.ContextCustomizerSpringRunnerTests.CustomTestContextBootstrapper; +import org.springframework.test.context.support.DefaultTestContextBootstrapper; + +import static java.util.Collections.*; +import static org.junit.Assert.*; + +/** + * JUnit 4 based integration test which verifies support of + * {@link ContextCustomizerFactory} and {@link ContextCustomizer}. + * + * @author Sam Brannen + * @author Phillip Webb + * @since 4.3 + */ +@RunWith(SpringRunner.class) +@BootstrapWith(CustomTestContextBootstrapper.class) +public class ContextCustomizerSpringRunnerTests { + + @Autowired String foo; + + + @Test + public void injectedBean() { + assertEquals("foo", foo); + } + + + static class CustomTestContextBootstrapper extends DefaultTestContextBootstrapper { + + @Override + protected List<ContextCustomizerFactory> getContextCustomizerFactories() { + return singletonList( + (ContextCustomizerFactory) (testClass, configAttributes) -> + (ContextCustomizer) (context, mergedConfig) -> context.getBeanFactory().registerSingleton("foo", "foo") + ); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/CustomDefaultContextLoaderClassSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/CustomDefaultContextLoaderClassSpringRunnerTests.java index aab80b71..be8a2ff9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/CustomDefaultContextLoaderClassSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/CustomDefaultContextLoaderClassSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -37,7 +37,7 @@ import static org.junit.Assert.*; * @author Sam Brannen * @since 3.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @BootstrapWith(CustomDefaultContextLoaderClassSpringRunnerTests.PropertiesBasedTestContextBootstrapper.class) @ContextConfiguration("PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests-context.properties") public class CustomDefaultContextLoaderClassSpringRunnerTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java index 0c1f043a..1b027899 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -45,7 +45,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @see Transactional#transactionManager * @see DefaultRollbackFalseTransactionalTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(classes = EmbeddedPersonDatabaseTestsConfig.class, inheritLocations = false) @Transactional("txMgr") @Rollback(false) diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java index 984fc62f..49f70f6d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -45,7 +45,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @see Transactional#transactionManager * @see DefaultRollbackTrueTransactionalTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(classes = EmbeddedPersonDatabaseTestsConfig.class, inheritLocations = false) @Transactional("txMgr") @Rollback(true) diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/EnabledAndIgnoredSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/EnabledAndIgnoredSpringRunnerTests.java index a445fcaf..f4e84996 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/EnabledAndIgnoredSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/EnabledAndIgnoredSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -34,7 +34,7 @@ import static org.junit.Assert.*; * {@link IfProfileValue @IfProfileValue} and * {@link ProfileValueSourceConfiguration @ProfileValueSourceConfiguration} * (with the <em>implicit, default {@link ProfileValueSource}</em>) annotations in - * conjunction with the {@link SpringJUnit4ClassRunner}. + * conjunction with the {@link SpringRunner}. * <p> * Note that {@link TestExecutionListeners @TestExecutionListeners} is * explicitly configured with an empty list, thus disabling all default @@ -44,7 +44,7 @@ import static org.junit.Assert.*; * @since 2.5 * @see HardCodedProfileValueSourceSpringRunnerTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @TestExecutionListeners( {}) public class EnabledAndIgnoredSpringRunnerTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java index 5fc3947d..4cfb4699 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -29,7 +29,7 @@ import static org.springframework.test.context.junit4.JUnitTestingUtils.*; /** * Verifies proper handling of JUnit's {@link Test#expected() @Test(expected=...)} - * support in conjunction with the {@link SpringJUnit4ClassRunner}. + * support in conjunction with the {@link SpringRunner}. * * @author Sam Brannen * @since 3.0 @@ -39,7 +39,7 @@ public class ExpectedExceptionSpringRunnerTests { @Test public void expectedExceptions() throws Exception { - runTestsAndAssertCounters(SpringJUnit4ClassRunner.class, ExpectedExceptionSpringRunnerTestCase.class, 1, 0, 1, 0, 0); + runTestsAndAssertCounters(SpringRunner.class, ExpectedExceptionSpringRunnerTestCase.class, 1, 0, 1, 0, 0); } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsJUnitTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsJUnitTests.java index daebe2bc..4918606f 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsJUnitTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsJUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -79,7 +79,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests { } protected Class<? extends Runner> getRunnerClass() { - return SpringJUnit4ClassRunner.class; + return SpringRunner.class; } @Test @@ -133,7 +133,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests { } } - @RunWith(SpringJUnit4ClassRunner.class) + @RunWith(SpringRunner.class) @TestExecutionListeners({}) public static abstract class BaseTestCase { @@ -168,7 +168,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests { } @Ignore("TestCase classes are run manually by the enclosing test class") - @RunWith(SpringJUnit4ClassRunner.class) + @RunWith(SpringRunner.class) @ContextConfiguration("FailingBeforeAndAfterMethodsTests-context.xml") @Transactional public static class FailingBeforeTransactionTestCase { @@ -184,7 +184,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests { } @Ignore("TestCase classes are run manually by the enclosing test class") - @RunWith(SpringJUnit4ClassRunner.class) + @RunWith(SpringRunner.class) @ContextConfiguration("FailingBeforeAndAfterMethodsTests-context.xml") @Transactional public static class FailingAfterTransactionTestCase { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/HardCodedProfileValueSourceSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/HardCodedProfileValueSourceSpringRunnerTests.java index 9a26751f..b0e18843 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/HardCodedProfileValueSourceSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/HardCodedProfileValueSourceSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -28,7 +28,7 @@ import org.springframework.test.annotation.ProfileValueSourceConfiguration; * @IfProfileValue} and {@link ProfileValueSourceConfiguration * @ProfileValueSourceConfiguration} (with an * <em>explicit, custom defined {@link ProfileValueSource}</em>) annotations in - * conjunction with the {@link SpringJUnit4ClassRunner}. + * conjunction with the {@link SpringRunner}. * </p> * * @author Sam Brannen diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/MethodLevelTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/MethodLevelTransactionalSpringRunnerTests.java index 42700595..f9b6b749 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/MethodLevelTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/MethodLevelTransactionalSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -40,7 +40,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * {@link Transactional @Transactional}, {@link TestExecutionListeners * @TestExecutionListeners}, and {@link ContextConfiguration * @ContextConfiguration} annotations in conjunction with the - * {@link SpringJUnit4ClassRunner} and the following + * {@link SpringRunner} and the following * {@link TestExecutionListener TestExecutionListeners}: * * <ul> diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/OptionalContextConfigurationSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/OptionalContextConfigurationSpringRunnerTests.java new file mode 100644 index 00000000..5cb4ce83 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/OptionalContextConfigurationSpringRunnerTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2016 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.test.context.junit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.junit.Assert.assertEquals; + +/** + * JUnit 4 based integration test which verifies that {@link @ContextConfiguration} + * is optional. + * + * @author Phillip Webb + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class OptionalContextConfigurationSpringRunnerTests { + + @Autowired + String foo; + + + @Test + public void contextConfigurationAnnotationIsOptional() { + assertEquals("foo", foo); + } + + + @Configuration + static class Config { + + @Bean + String foo() { + return "foo"; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.java index acbb6cc2..b52a9fa1 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -32,7 +32,7 @@ import static org.junit.Assert.*; /** * <p> * JUnit 4 based test class, which verifies the expected functionality of - * {@link SpringJUnit4ClassRunner} in conjunction with support for application contexts + * {@link SpringRunner} in conjunction with support for application contexts * loaded from Java {@link Properties} files. Specifically, the * {@link ContextConfiguration#loader() loader} attribute of {@code ContextConfiguration} * and the @@ -54,7 +54,7 @@ import static org.junit.Assert.*; * @see GenericPropertiesContextLoader * @see SpringJUnit4ClassRunnerAppCtxTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(loader = GenericPropertiesContextLoader.class) public class PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java index 94a884bf..d2bf46bf 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -38,7 +38,7 @@ import static org.springframework.test.context.junit4.JUnitTestingUtils.*; /** * Verifies proper handling of the following in conjunction with the - * {@link SpringJUnit4ClassRunner}: + * {@link SpringRunner}: * <ul> * <li>Spring's {@link Repeat @Repeat}</li> * <li>Spring's {@link Timed @Timed}</li> @@ -82,7 +82,7 @@ public class RepeatedSpringRunnerTests { } protected Class<? extends Runner> getRunnerClass() { - return SpringJUnit4ClassRunner.class; + return SpringRunner.class; } @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit47ClassRunnerRuleTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit47ClassRunnerRuleTests.java index 6f0eddff..e59cdde9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit47ClassRunnerRuleTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit47ClassRunnerRuleTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -27,14 +27,14 @@ import static org.junit.Assert.*; /** * Verifies support for JUnit 4.7 {@link Rule Rules} in conjunction with the - * {@link SpringJUnit4ClassRunner}. The body of this test class is taken from - * the JUnit 4.7 release notes. + * {@link SpringRunner}. The body of this test class is taken from the + * JUnit 4.7 release notes. * * @author JUnit 4.7 Team * @author Sam Brannen * @since 3.0 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @TestExecutionListeners( {}) public class SpringJUnit47ClassRunnerRuleTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunnerAppCtxTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunnerAppCtxTests.java index 292aebfc..c60745d3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunnerAppCtxTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunnerAppCtxTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -43,7 +43,7 @@ import static org.junit.Assert.*; /** * SpringJUnit4ClassRunnerAppCtxTests serves as a <em>proof of concept</em> * JUnit 4 based test class, which verifies the expected functionality of - * {@link SpringJUnit4ClassRunner} in conjunction with the following: + * {@link SpringRunner} in conjunction with the following: * * <ul> * <li>{@link ContextConfiguration @ContextConfiguration}</li> @@ -73,7 +73,7 @@ import static org.junit.Assert.*; * @see RelativePathSpringJUnit4ClassRunnerAppCtxTests * @see InheritedConfigSpringJUnit4ClassRunnerAppCtxTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @TestExecutionListeners(DependencyInjectionTestExecutionListener.class) public class SpringJUnit4ClassRunnerAppCtxTests implements ApplicationContextAware, BeanNameAware, InitializingBean { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java index 8f301117..020bda60 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -45,12 +45,12 @@ import org.springframework.test.context.junit4.profile.xml.DevProfileXmlConfigTe import org.springframework.test.context.transaction.programmatic.ProgrammaticTxMgmtTests; /** - * JUnit test suite for tests involving {@link SpringJUnit4ClassRunner} and the + * JUnit test suite for tests involving {@link SpringRunner} and the * <em>Spring TestContext Framework</em>; only intended to be run manually as a * convenience. * * <p>This test suite serves a dual purpose of verifying that tests run with - * {@link SpringJUnit4ClassRunner} can be used in conjunction with JUnit's + * {@link SpringRunner} can be used in conjunction with JUnit's * {@link Suite} runner. * * <p>Note that tests included in this suite will be executed at least twice if diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/StandardJUnit4FeaturesSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/StandardJUnit4FeaturesSpringRunnerTests.java index 4dd270ca..f4cda4ea 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/StandardJUnit4FeaturesSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/StandardJUnit4FeaturesSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2016 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. @@ -22,7 +22,7 @@ import org.springframework.test.context.TestExecutionListeners; /** * <p> - * Simple unit test to verify that {@link SpringJUnit4ClassRunner} does not + * Simple unit test to verify that {@link SpringRunner} does not * hinder correct functionality of standard JUnit 4.4+ testing features. * </p> * <p> @@ -35,7 +35,7 @@ import org.springframework.test.context.TestExecutionListeners; * @since 2.5 * @see StandardJUnit4FeaturesTests */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @TestExecutionListeners({}) public class StandardJUnit4FeaturesSpringRunnerTests extends StandardJUnit4FeaturesTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java index d59bc140..cede912c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -32,7 +32,7 @@ import static org.springframework.test.context.junit4.JUnitTestingUtils.*; /** * Verifies proper handling of the following in conjunction with the - * {@link SpringJUnit4ClassRunner}: + * {@link SpringRunner}: * <ul> * <li>JUnit's {@link Test#timeout() @Test(timeout=...)}</li> * <li>Spring's {@link Timed @Timed}</li> @@ -49,7 +49,7 @@ public class TimedSpringRunnerTests { } protected Class<? extends Runner> getRunnerClass() { - return SpringJUnit4ClassRunner.class; + return SpringRunner.class; } @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/TimedTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/TimedTransactionalSpringRunnerTests.java index 3fcdb040..cffe292f 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/TimedTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/TimedTransactionalSpringRunnerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -36,7 +36,7 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @author Sam Brannen * @since 2.5 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("transactionalTests-context.xml") @Transactional public class TimedTransactionalSpringRunnerTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/BarConfig.java b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/BarConfig.java new file mode 100644 index 00000000..1ee6b6fd --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/BarConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2016 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.test.context.junit4.aci.annotation; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@Configuration +class BarConfig { + + @Bean + String bar() { + return "bar"; + } + +}
\ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/FooConfig.java b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/FooConfig.java new file mode 100644 index 00000000..a080fd84 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/FooConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2016 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.test.context.junit4.aci.annotation; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@Configuration +class FooConfig { + + @Bean + String foo() { + return "foo"; + } + +}
\ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/InitializerConfiguredViaMetaAnnotationTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/InitializerConfiguredViaMetaAnnotationTests.java new file mode 100644 index 00000000..971e3f4b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/aci/annotation/InitializerConfiguredViaMetaAnnotationTests.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2016 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.test.context.junit4.aci.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit4.aci.annotation.InitializerConfiguredViaMetaAnnotationTests.ComposedContextConfiguration; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import static org.junit.Assert.assertEquals; + +/** + * Integration test that demonstrates how to register one or more {@code @Configuration} + * classes via an {@link ApplicationContextInitializer} in a composed annotation so + * that certain {@code @Configuration} classes are always registered whenever the composed + * annotation is used, even if the composed annotation is used to declare additional + * {@code @Configuration} classes. + * + * <p>This class has been implemented in response to the following Stack Overflow question: + * <a href="http://stackoverflow.com/questions/35733344/can-contextconfiguration-in-a-custom-annotation-be-merged"> + * Can {@code @ContextConfiguration} in a custom annotation be merged?</a> + * + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +@ComposedContextConfiguration(BarConfig.class) +public class InitializerConfiguredViaMetaAnnotationTests { + + @Autowired + String foo; + + @Autowired + String bar; + + @Autowired + List<String> strings; + + + @Test + public void beansFromInitializerAndComposedAnnotation() { + assertEquals(2, strings.size()); + assertEquals("foo", foo); + assertEquals("bar", bar); + } + + + static class FooConfigInitializer implements ApplicationContextInitializer<GenericApplicationContext> { + + @Override + public void initialize(GenericApplicationContext applicationContext) { + new AnnotatedBeanDefinitionReader(applicationContext).register(FooConfig.class); + } + } + + @ContextConfiguration(loader = AnnotationConfigContextLoader.class, initializers = FooConfigInitializer.class) + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @interface ComposedContextConfiguration { + + @AliasFor(annotation = ContextConfiguration.class, attribute = "classes") + Class<?>[] value() default {}; + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsContextInitializerTests.java b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsContextInitializerTests.java index 4b70a8cb..f92c7418 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsContextInitializerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsContextInitializerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -16,6 +16,7 @@ package org.springframework.test.context.support; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -35,63 +36,62 @@ import org.springframework.web.context.support.GenericWebApplicationContext; * @author Sam Brannen * @since 3.1 */ +@SuppressWarnings("unchecked") public class BootstrapTestUtilsContextInitializerTests extends AbstractContextConfigurationUtilsTests { @Test - public void buildMergedConfigWithLocalInitializer() { - Class<?> testClass = InitializersFoo.class; - Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class }; - Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses// - = new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>(); - expectedInitializerClasses.add(FooInitializer.class); + public void buildMergedConfigWithSingleLocalInitializer() { + Class<?> testClass = SingleInitializer.class; + MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); + + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, + initializers(FooInitializer.class), DelegatingSmartContextLoader.class); + } + @Test + public void buildMergedConfigWithLocalInitializerAndConfigClass() { + Class<?> testClass = InitializersFoo.class; MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); - assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses, - DelegatingSmartContextLoader.class); + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, classes(FooConfig.class), + initializers(FooInitializer.class), DelegatingSmartContextLoader.class); } @Test public void buildMergedConfigWithLocalAndInheritedInitializer() { Class<?> testClass = InitializersBar.class; - Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class }; - Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses// - = new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>(); - expectedInitializerClasses.add(FooInitializer.class); - expectedInitializerClasses.add(BarInitializer.class); - MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); - assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses, - DelegatingSmartContextLoader.class); + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, classes(FooConfig.class, BarConfig.class), + initializers(FooInitializer.class, BarInitializer.class), DelegatingSmartContextLoader.class); } @Test public void buildMergedConfigWithOverriddenInitializers() { Class<?> testClass = OverriddenInitializersBar.class; - Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class }; - Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses// - = new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>(); - expectedInitializerClasses.add(BarInitializer.class); - MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); - assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses, - DelegatingSmartContextLoader.class); + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, classes(FooConfig.class, BarConfig.class), + initializers(BarInitializer.class), DelegatingSmartContextLoader.class); } @Test public void buildMergedConfigWithOverriddenInitializersAndClasses() { Class<?> testClass = OverriddenInitializersAndClassesBar.class; - Class<?>[] expectedClasses = new Class<?>[] { BarConfig.class }; - Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses// - = new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>(); - expectedInitializerClasses.add(BarInitializer.class); - MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); - assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses, - DelegatingSmartContextLoader.class); + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, classes(BarConfig.class), + initializers(BarInitializer.class), DelegatingSmartContextLoader.class); + } + + private Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializers( + Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>... classes) { + + return new HashSet<>(Arrays.asList(classes)); + } + + private Class<?>[] classes(Class<?>... classes) { + return classes; } @@ -109,6 +109,10 @@ public class BootstrapTestUtilsContextInitializerTests extends AbstractContextCo } } + @ContextConfiguration(initializers = FooInitializer.class) + private static class SingleInitializer { + } + @ContextConfiguration(classes = FooConfig.class, initializers = FooInitializer.class) private static class InitializersFoo { } diff --git a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java index cef782e2..b499c257 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -21,15 +21,20 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.test.context.BootstrapTestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextLoader; import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.web.WebDelegatingSmartContextLoader; import org.springframework.test.context.web.WebMergedContextConfiguration; -import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; /** * Unit tests for {@link BootstrapTestUtils} involving {@link MergedContextConfiguration}. @@ -39,12 +44,28 @@ import static org.junit.Assert.*; */ public class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUtilsTests { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test - public void buildMergedConfigWithoutAnnotation() { + public void buildImplicitMergedConfigWithoutAnnotation() { Class<?> testClass = Enigma.class; MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass); - assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, null); + assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, DelegatingSmartContextLoader.class); + } + + /** + * @since 4.3 + */ + @Test + public void buildMergedConfigWithContextConfigurationWithoutLocationsClassesOrInitializers() { + exception.expect(IllegalStateException.class); + exception.expectMessage(startsWith("DelegatingSmartContextLoader was unable to detect defaults, " + + "and no ApplicationContextInitializers or ContextCustomizers were declared for context configuration attributes")); + + buildMergedContextConfiguration(MissingContextAttributesTestCase.class); } @Test @@ -200,4 +221,8 @@ public class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigur public static class GermanShepherd extends WorkingDog { } + @ContextConfiguration + static class MissingContextAttributesTestCase { + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/support/ContextLoaderUtilsContextHierarchyTests.java b/spring-test/src/test/java/org/springframework/test/context/support/ContextLoaderUtilsContextHierarchyTests.java index 3faab204..37025fdf 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/ContextLoaderUtilsContextHierarchyTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/ContextLoaderUtilsContextHierarchyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -59,9 +59,13 @@ public class ContextLoaderUtilsContextHierarchyTests extends AbstractContextConf resolveContextHierarchyAttributes(SingleTestClassWithContextConfigurationAndContextHierarchyOnSingleMetaAnnotation.class); } - @Test(expected = IllegalStateException.class) + @Test public void resolveContextHierarchyAttributesForSingleTestClassWithImplicitSingleLevelContextHierarchy() { - resolveContextHierarchyAttributes(BareAnnotations.class); + List<List<ContextConfigurationAttributes>> hierarchyAttributes = resolveContextHierarchyAttributes(BareAnnotations.class); + assertEquals(1, hierarchyAttributes.size()); + List<ContextConfigurationAttributes> configAttributesList = hierarchyAttributes.get(0); + assertEquals(1, configAttributesList.size()); + debugConfigAttributes(configAttributesList); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java b/spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java index 0395ee36..8f416cfa 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -56,17 +56,6 @@ public class DelegatingSmartContextLoaderTests { // --- SmartContextLoader - processContextConfiguration() ------------------ @Test - public void processContextConfigurationWithoutLocationsAndConfigurationClassesForBogusTestClass() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(startsWith("Neither")); - expectedException.expectMessage(containsString("was able to detect defaults")); - - ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(getClass(), - EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class); - loader.processContextConfiguration(configAttributes); - } - - @Test public void processContextConfigurationWithDefaultXmlConfigGeneration() { ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(XmlTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class); diff --git a/spring-test/src/test/java/org/springframework/test/context/support/TestPropertySourceUtilsTests.java b/spring-test/src/test/java/org/springframework/test/context/support/TestPropertySourceUtilsTests.java index 8f6c8d7e..b1d7ddfd 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/TestPropertySourceUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/TestPropertySourceUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -26,13 +26,17 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.ResourceLoader; import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockPropertySource; import org.springframework.test.context.TestPropertySource; import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; import static org.springframework.test.context.support.TestPropertySourceUtils.*; /** @@ -44,20 +48,16 @@ import static org.springframework.test.context.support.TestPropertySourceUtils.* public class TestPropertySourceUtilsTests { private static final String[] EMPTY_STRING_ARRAY = new String[0]; - private static final String[] KEY_VALUE_PAIR = new String[] { "key = value" }; + + private static final String[] KEY_VALUE_PAIR = new String[] {"key = value"}; + + private static final String[] FOO_LOCATIONS = new String[] {"classpath:/foo.properties"}; + @Rule public ExpectedException expectedException = ExpectedException.none(); - private void assertMergedTestPropertySources(Class<?> testClass, String[] expectedLocations, - String[] expectedProperties) { - MergedTestPropertySources mergedPropertySources = buildMergedTestPropertySources(testClass); - assertNotNull(mergedPropertySources); - assertArrayEquals(expectedLocations, mergedPropertySources.getLocations()); - assertArrayEquals(expectedProperties, mergedPropertySources.getProperties()); - } - @Test public void emptyAnnotation() { expectedException.expect(IllegalStateException.class); @@ -76,8 +76,8 @@ public class TestPropertySourceUtilsTests { @Test public void value() { - assertMergedTestPropertySources(ValuePropertySources.class, new String[] { "classpath:/value.xml" }, - EMPTY_STRING_ARRAY); + assertMergedTestPropertySources(ValuePropertySources.class, asArray("classpath:/value.xml"), + EMPTY_STRING_ARRAY); } @Test @@ -88,44 +88,88 @@ public class TestPropertySourceUtilsTests { @Test public void locationsAndProperties() { - assertMergedTestPropertySources(LocationsAndPropertiesPropertySources.class, new String[] { - "classpath:/foo1.xml", "classpath:/foo2.xml" }, new String[] { "k1a=v1a", "k1b: v1b" }); + assertMergedTestPropertySources(LocationsAndPropertiesPropertySources.class, + asArray("classpath:/foo1.xml", "classpath:/foo2.xml"), asArray("k1a=v1a", "k1b: v1b")); } @Test public void inheritedLocationsAndProperties() { - assertMergedTestPropertySources(InheritedPropertySources.class, new String[] { "classpath:/foo1.xml", - "classpath:/foo2.xml" }, new String[] { "k1a=v1a", "k1b: v1b" }); + assertMergedTestPropertySources(InheritedPropertySources.class, + asArray("classpath:/foo1.xml", "classpath:/foo2.xml"), asArray("k1a=v1a", "k1b: v1b")); } @Test public void extendedLocationsAndProperties() { - assertMergedTestPropertySources(ExtendedPropertySources.class, new String[] { "classpath:/foo1.xml", - "classpath:/foo2.xml", "classpath:/bar1.xml", "classpath:/bar2.xml" }, new String[] { "k1a=v1a", - "k1b: v1b", "k2a v2a", "k2b: v2b" }); + assertMergedTestPropertySources(ExtendedPropertySources.class, + asArray("classpath:/foo1.xml", "classpath:/foo2.xml", "classpath:/bar1.xml", "classpath:/bar2.xml"), + asArray("k1a=v1a", "k1b: v1b", "k2a v2a", "k2b: v2b")); } @Test public void overriddenLocations() { assertMergedTestPropertySources(OverriddenLocationsPropertySources.class, - new String[] { "classpath:/baz.properties" }, new String[] { "k1a=v1a", "k1b: v1b", "key = value" }); + asArray("classpath:/baz.properties"), asArray("k1a=v1a", "k1b: v1b", "key = value")); } @Test public void overriddenProperties() { - assertMergedTestPropertySources(OverriddenPropertiesPropertySources.class, new String[] { - "classpath:/foo1.xml", "classpath:/foo2.xml", "classpath:/baz.properties" }, KEY_VALUE_PAIR); + assertMergedTestPropertySources(OverriddenPropertiesPropertySources.class, + asArray("classpath:/foo1.xml", "classpath:/foo2.xml", "classpath:/baz.properties"), KEY_VALUE_PAIR); } @Test public void overriddenLocationsAndProperties() { assertMergedTestPropertySources(OverriddenLocationsAndPropertiesPropertySources.class, - new String[] { "classpath:/baz.properties" }, KEY_VALUE_PAIR); + asArray("classpath:/baz.properties"), KEY_VALUE_PAIR); + } + + + @Test + public void addPropertiesFilesToEnvironmentWithNullContext() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("must not be null"); + addPropertiesFilesToEnvironment((ConfigurableApplicationContext) null, FOO_LOCATIONS); + } + + @Test + public void addPropertiesFilesToEnvironmentWithContextAndNullLocations() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("must not be null"); + addPropertiesFilesToEnvironment(mock(ConfigurableApplicationContext.class), (String[]) null); + } + + @Test + public void addPropertiesFilesToEnvironmentWithNullEnvironment() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("must not be null"); + addPropertiesFilesToEnvironment((ConfigurableEnvironment) null, mock(ResourceLoader.class), FOO_LOCATIONS); + } + + @Test + public void addPropertiesFilesToEnvironmentWithEnvironmentAndNullLocations() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("must not be null"); + addPropertiesFilesToEnvironment(new MockEnvironment(), mock(ResourceLoader.class), (String[]) null); + } + + @Test + public void addPropertiesFilesToEnvironmentWithSinglePropertyFromVirtualFile() { + ConfigurableEnvironment environment = new MockEnvironment(); + + MutablePropertySources propertySources = environment.getPropertySources(); + propertySources.remove(MockPropertySource.MOCK_PROPERTIES_PROPERTY_SOURCE_NAME); + assertEquals(0, propertySources.size()); + + String pair = "key = value"; + ByteArrayResource resource = new ByteArrayResource(pair.getBytes(), "from inlined property: " + pair); + ResourceLoader resourceLoader = mock(ResourceLoader.class); + when(resourceLoader.getResource(anyString())).thenReturn(resource); + + addPropertiesFilesToEnvironment(environment, resourceLoader, FOO_LOCATIONS); + assertEquals(1, propertySources.size()); + assertEquals("value", environment.getProperty("key")); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithNullContext() { expectedException.expect(IllegalArgumentException.class); @@ -133,19 +177,13 @@ public class TestPropertySourceUtilsTests { addInlinedPropertiesToEnvironment((ConfigurableApplicationContext) null, KEY_VALUE_PAIR); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithContextAndNullInlinedProperties() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("inlined"); - addInlinedPropertiesToEnvironment(mock(ConfigurableApplicationContext.class), null); + addInlinedPropertiesToEnvironment(mock(ConfigurableApplicationContext.class), (String[]) null); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithNullEnvironment() { expectedException.expect(IllegalArgumentException.class); @@ -153,39 +191,27 @@ public class TestPropertySourceUtilsTests { addInlinedPropertiesToEnvironment((ConfigurableEnvironment) null, KEY_VALUE_PAIR); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithEnvironmentAndNullInlinedProperties() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("inlined"); - addInlinedPropertiesToEnvironment(new MockEnvironment(), null); + addInlinedPropertiesToEnvironment(new MockEnvironment(), (String[]) null); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithMalformedUnicodeInValue() { expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Failed to load test environment property"); - addInlinedPropertiesToEnvironment(new MockEnvironment(), new String[] { "key = \\uZZZZ" }); + addInlinedPropertiesToEnvironment(new MockEnvironment(), asArray("key = \\uZZZZ")); } - /** - * @since 4.1.5 - */ @Test public void addInlinedPropertiesToEnvironmentWithMultipleKeyValuePairsInSingleInlinedProperty() { expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Failed to load exactly one test environment property"); - addInlinedPropertiesToEnvironment(new MockEnvironment(), new String[] { "a=b\nx=y" }); + addInlinedPropertiesToEnvironment(new MockEnvironment(), asArray("a=b\nx=y")); } - /** - * @since 4.1.5 - */ @Test @SuppressWarnings("rawtypes") public void addInlinedPropertiesToEnvironmentWithEmptyProperty() { @@ -193,7 +219,7 @@ public class TestPropertySourceUtilsTests { MutablePropertySources propertySources = environment.getPropertySources(); propertySources.remove(MockPropertySource.MOCK_PROPERTIES_PROPERTY_SOURCE_NAME); assertEquals(0, propertySources.size()); - addInlinedPropertiesToEnvironment(environment, new String[] { " " }); + addInlinedPropertiesToEnvironment(environment, asArray(" ")); assertEquals(1, propertySources.size()); assertEquals(0, ((Map) propertySources.iterator().next().getSource()).size()); } @@ -202,10 +228,25 @@ public class TestPropertySourceUtilsTests { public void convertInlinedPropertiesToMapWithNullInlinedProperties() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("inlined"); - convertInlinedPropertiesToMap(null); + convertInlinedPropertiesToMap((String[]) null); + } + + + private static void assertMergedTestPropertySources(Class<?> testClass, String[] expectedLocations, + String[] expectedProperties) { + + MergedTestPropertySources mergedPropertySources = buildMergedTestPropertySources(testClass); + assertNotNull(mergedPropertySources); + assertArrayEquals(expectedLocations, mergedPropertySources.getLocations()); + assertArrayEquals(expectedProperties, mergedPropertySources.getProperties()); + } + + + @SafeVarargs + private static <T> T[] asArray(T... arr) { + return arr; } - // ------------------------------------------------------------------- @TestPropertySource static class EmptyPropertySources { diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/AnnotationConfigTransactionalTestNGSpringContextTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/AnnotationConfigTransactionalTestNGSpringContextTests.java index a7c9f974..6c515027 100644 --- a/spring-test/src/test/java/org/springframework/test/context/testng/AnnotationConfigTransactionalTestNGSpringContextTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/testng/AnnotationConfigTransactionalTestNGSpringContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -54,8 +54,8 @@ import static org.testng.Assert.*; * @since 3.1 */ @ContextConfiguration -public class AnnotationConfigTransactionalTestNGSpringContextTests extends - AbstractTransactionalTestNGSpringContextTests { +public class AnnotationConfigTransactionalTestNGSpringContextTests + extends AbstractTransactionalTestNGSpringContextTests { private static final String JANE = "jane"; private static final String SUE = "sue"; @@ -94,7 +94,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @BeforeClass - public void beforeClass() { + void beforeClass() { numSetUpCalls = 0; numSetUpCallsInTransaction = 0; numTearDownCalls = 0; @@ -102,7 +102,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @AfterClass - public void afterClass() { + void afterClass() { assertEquals(numSetUpCalls, NUM_TESTS, "number of calls to setUp()."); assertEquals(numSetUpCallsInTransaction, NUM_TX_TESTS, "number of calls to setUp() within a transaction."); assertEquals(numTearDownCalls, NUM_TESTS, "number of calls to tearDown()."); @@ -111,7 +111,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void autowiringFromConfigClass() { + void autowiringFromConfigClass() { assertNotNull(employee, "The employee should have been autowired."); assertEquals(employee.getName(), "John Smith"); @@ -120,13 +120,13 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @BeforeTransaction - public void beforeTransaction() { + void beforeTransaction() { assertNumRowsInPersonTable(1, "before a transactional test method"); assertAddPerson(YODA); } @BeforeMethod - public void setUp() throws Exception { + void setUp() throws Exception { numSetUpCalls++; if (inTransaction()) { numSetUpCallsInTransaction++; @@ -135,7 +135,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @Test - public void modifyTestDataWithinTransaction() { + void modifyTestDataWithinTransaction() { assertInTransaction(true); assertAddPerson(JANE); assertAddPerson(SUE); @@ -143,7 +143,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @AfterMethod - public void tearDown() throws Exception { + void tearDown() throws Exception { numTearDownCalls++; if (inTransaction()) { numTearDownCallsInTransaction++; @@ -152,7 +152,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @AfterTransaction - public void afterTransaction() { + void afterTransaction() { assertEquals(deletePerson(YODA), 1, "Deleting yoda"); assertNumRowsInPersonTable(1, "after a transactional test method"); } @@ -162,7 +162,7 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends static class ContextConfiguration { @Bean - public Employee employee() { + Employee employee() { Employee employee = new Employee(); employee.setName("John Smith"); employee.setAge(42); @@ -171,17 +171,17 @@ public class AnnotationConfigTransactionalTestNGSpringContextTests extends } @Bean - public Pet pet() { + Pet pet() { return new Pet("Fido"); } @Bean - public PlatformTransactionManager transactionManager() { + PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean - public DataSource dataSource() { + DataSource dataSource() { return new EmbeddedDatabaseBuilder()// .addScript("classpath:/org/springframework/test/jdbc/schema.sql")// .addScript("classpath:/org/springframework/test/jdbc/data.sql")// diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/ConcreteTransactionalTestNGSpringContextTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/ConcreteTransactionalTestNGSpringContextTests.java index 2acc370e..d249fc38 100644 --- a/spring-test/src/test/java/org/springframework/test/context/testng/ConcreteTransactionalTestNGSpringContextTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/testng/ConcreteTransactionalTestNGSpringContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -117,7 +117,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans } @BeforeClass - public void beforeClass() { + void beforeClass() { numSetUpCalls = 0; numSetUpCallsInTransaction = 0; numTearDownCalls = 0; @@ -125,7 +125,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans } @AfterClass - public void afterClass() { + void afterClass() { assertEquals(numSetUpCalls, NUM_TESTS, "number of calls to setUp()."); assertEquals(numSetUpCallsInTransaction, NUM_TX_TESTS, "number of calls to setUp() within a transaction."); assertEquals(numTearDownCalls, NUM_TESTS, "number of calls to tearDown()."); @@ -134,7 +134,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyApplicationContextSet() { + void verifyApplicationContextSet() { assertInTransaction(false); assertNotNull(super.applicationContext, "The application context should have been set due to ApplicationContextAware semantics."); @@ -144,7 +144,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyBeanInitialized() { + void verifyBeanInitialized() { assertInTransaction(false); assertTrue(beanInitialized, "This test instance should have been initialized due to InitializingBean semantics."); @@ -152,7 +152,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyBeanNameSet() { + void verifyBeanNameSet() { assertInTransaction(false); assertEquals(beanName, getClass().getName(), "The bean name of this test instance should have been set due to BeanNameAware semantics."); @@ -160,7 +160,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyAnnotationAutowiredFields() { + void verifyAnnotationAutowiredFields() { assertInTransaction(false); assertNull(nonrequiredLong, "The nonrequiredLong field should NOT have been autowired."); assertNotNull(pet, "The pet field should have been autowired."); @@ -169,7 +169,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyAnnotationAutowiredMethods() { + void verifyAnnotationAutowiredMethods() { assertInTransaction(false); assertNotNull(employee, "The setEmployee() method should have been autowired."); assertEquals(employee.getName(), "John Smith", "employee's name."); @@ -177,26 +177,26 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyResourceAnnotationInjectedFields() { + void verifyResourceAnnotationInjectedFields() { assertInTransaction(false); assertEquals(foo, "Foo", "The foo field should have been injected via @Resource."); } @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) - public void verifyResourceAnnotationInjectedMethods() { + void verifyResourceAnnotationInjectedMethods() { assertInTransaction(false); assertEquals(bar, "Bar", "The setBar() method should have been injected via @Resource."); } @BeforeTransaction - public void beforeTransaction() { + void beforeTransaction() { assertNumRowsInPersonTable(1, "before a transactional test method"); assertAddPerson(YODA); } @BeforeMethod - public void setUp() throws Exception { + void setUp() throws Exception { numSetUpCalls++; if (inTransaction()) { numSetUpCallsInTransaction++; @@ -205,7 +205,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans } @Test - public void modifyTestDataWithinTransaction() { + void modifyTestDataWithinTransaction() { assertInTransaction(true); assertAddPerson(JANE); assertAddPerson(SUE); @@ -213,7 +213,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans } @AfterMethod - public void tearDown() throws Exception { + void tearDown() throws Exception { numTearDownCalls++; if (inTransaction()) { numTearDownCallsInTransaction++; @@ -222,7 +222,7 @@ public class ConcreteTransactionalTestNGSpringContextTests extends AbstractTrans } @AfterTransaction - public void afterTransaction() { + void afterTransaction() { assertEquals(deletePerson(YODA), 1, "Deleting yoda"); assertNumRowsInPersonTable(1, "after a transactional test method"); } diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/web/ServletTestExecutionListenerTestNGIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/web/ServletTestExecutionListenerTestNGIntegrationTests.java index 25f33425..6de10205 100644 --- a/spring-test/src/test/java/org/springframework/test/context/testng/web/ServletTestExecutionListenerTestNGIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/testng/web/ServletTestExecutionListenerTestNGIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -57,7 +57,7 @@ public class ServletTestExecutionListenerTestNGIntegrationTests extends Abstract * @see #ensureMocksAreReinjectedBetweenTests_2 */ @Test - public void ensureMocksAreReinjectedBetweenTests_1() { + void ensureMocksAreReinjectedBetweenTests_1() { assertInjectedServletRequestEqualsRequestInRequestContextHolder(); } @@ -67,7 +67,7 @@ public class ServletTestExecutionListenerTestNGIntegrationTests extends Abstract * @see #ensureMocksAreReinjectedBetweenTests_1 */ @Test - public void ensureMocksAreReinjectedBetweenTests_2() { + void ensureMocksAreReinjectedBetweenTests_2() { assertInjectedServletRequestEqualsRequestInRequestContextHolder(); } diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/web/TestNGSpringContextWebTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/web/TestNGSpringContextWebTests.java index 9092c3fe..c14c0f24 100644 --- a/spring-test/src/test/java/org/springframework/test/context/testng/web/TestNGSpringContextWebTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/testng/web/TestNGSpringContextWebTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -52,34 +52,34 @@ public class TestNGSpringContextWebTests extends AbstractTestNGSpringContextTest static class Config { @Bean - public String foo() { + String foo() { return "enigma"; } } - protected ServletContext servletContext; + ServletContext servletContext; @Autowired - protected WebApplicationContext wac; + WebApplicationContext wac; @Autowired - protected MockServletContext mockServletContext; + MockServletContext mockServletContext; @Autowired - protected MockHttpServletRequest request; + MockHttpServletRequest request; @Autowired - protected MockHttpServletResponse response; + MockHttpServletResponse response; @Autowired - protected MockHttpSession session; + MockHttpSession session; @Autowired - protected ServletWebRequest webRequest; + ServletWebRequest webRequest; @Autowired - protected String foo; + String foo; @Override @@ -88,7 +88,7 @@ public class TestNGSpringContextWebTests extends AbstractTestNGSpringContextTest } @Test - public void basicWacFeatures() throws Exception { + void basicWacFeatures() throws Exception { assertNotNull("ServletContext should be set in the WAC.", wac.getServletContext()); assertNotNull("ServletContext should have been set via ServletContextAware.", servletContext); @@ -112,7 +112,7 @@ public class TestNGSpringContextWebTests extends AbstractTestNGSpringContextTest } @Test - public void fooEnigmaAutowired() { + void fooEnigmaAutowired() { assertEquals("enigma", foo); } diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java new file mode 100644 index 00000000..d9cd1526 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java @@ -0,0 +1,122 @@ +/* + * Copyright 2002-2016 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.test.context.transaction; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; +import org.springframework.test.transaction.TransactionTestUtils; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.Assert.*; + +/** + * Integration tests that ensure that <em>primary</em> transaction managers + * are supported. + * + * @author Sam Brannen + * @since 4.3 + * @see org.springframework.test.context.jdbc.PrimaryDataSourceTests + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@DirtiesContext +public class PrimaryTransactionManagerTests { + + @Configuration + static class Config { + + @Primary + @Bean + public PlatformTransactionManager primaryTransactionManager() { + return new DataSourceTransactionManager(dataSource1()); + } + + @Bean + public PlatformTransactionManager additionalTransactionManager() { + return new DataSourceTransactionManager(dataSource2()); + } + + @Bean + public DataSource dataSource1() { + // @formatter:off + return new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .addScript("classpath:/org/springframework/test/context/jdbc/schema.sql") + .build(); + // @formatter:on + } + + @Bean + public DataSource dataSource2() { + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); + } + + } + + + private JdbcTemplate jdbcTemplate; + + + @Autowired + public void setDataSource(DataSource dataSource1) { + this.jdbcTemplate = new JdbcTemplate(dataSource1); + } + + @BeforeTransaction + public void beforeTransaction() { + assertNumUsers(0); + } + + @Test + @Transactional + public void transactionalTest() { + TransactionTestUtils.assertInTransaction(true); + + ClassPathResource resource = new ClassPathResource("/org/springframework/test/context/jdbc/data.sql"); + new ResourceDatabasePopulator(resource).execute(jdbcTemplate.getDataSource()); + + assertNumUsers(1); + } + + @AfterTransaction + public void afterTransaction() { + assertNumUsers(0); + } + + private void assertNumUsers(int expected) { + assertEquals("Number of rows in the 'user' table.", expected, + JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user")); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java index 8d4e015f..82cb0081 100644 --- a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -37,7 +37,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.SimpleTransactionStatus; import static org.hamcrest.CoreMatchers.*; - import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; import static org.springframework.transaction.annotation.Propagation.*; @@ -55,6 +54,7 @@ public class TransactionalTestExecutionListenerTests { private final TransactionalTestExecutionListener listener = new TransactionalTestExecutionListener() { + @Override protected PlatformTransactionManager getTransactionManager(TestContext testContext, String qualifier) { return tm; } @@ -82,10 +82,10 @@ public class TransactionalTestExecutionListenerTests { given(testContext.getTestInstance()).willReturn(instance); given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest")); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); TransactionContextHolder.removeCurrentTransactionContext(); listener.beforeTestMethod(testContext); - assertEquals(invokedInTx, instance.invoked); + assertEquals(invokedInTx, instance.invoked()); } private void assertBeforeTestMethodWithNonTransactionalTestMethod(Class<? extends Invocable> clazz) @@ -95,10 +95,10 @@ public class TransactionalTestExecutionListenerTests { given(testContext.getTestInstance()).willReturn(instance); given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest")); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); TransactionContextHolder.removeCurrentTransactionContext(); listener.beforeTestMethod(testContext); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); } private void assertAfterTestMethod(Class<? extends Invocable> clazz) throws Exception { @@ -114,11 +114,12 @@ public class TransactionalTestExecutionListenerTests { given(tm.getTransaction(BDDMockito.any(TransactionDefinition.class))).willReturn(new SimpleTransactionStatus()); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); TransactionContextHolder.removeCurrentTransactionContext(); listener.beforeTestMethod(testContext); + assertFalse("callback should not have been invoked", instance.invoked()); listener.afterTestMethod(testContext); - assertTrue(instance.invoked); + assertTrue("callback should have been invoked", instance.invoked()); } private void assertAfterTestMethodWithNonTransactionalTestMethod(Class<? extends Invocable> clazz) throws Exception { @@ -127,11 +128,11 @@ public class TransactionalTestExecutionListenerTests { given(testContext.getTestInstance()).willReturn(instance); given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest")); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); TransactionContextHolder.removeCurrentTransactionContext(); listener.beforeTestMethod(testContext); listener.afterTestMethod(testContext); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); } private void assertTransactionConfigurationAttributes(Class<?> clazz, String transactionManagerName, @@ -174,7 +175,7 @@ public class TransactionalTestExecutionListenerTests { given(testContext.getTestInstance()).willReturn(instance); given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest")); - assertFalse(instance.invoked); + assertFalse("callback should not have been invoked", instance.invoked()); TransactionContextHolder.removeCurrentTransactionContext(); try { @@ -245,6 +246,16 @@ public class TransactionalTestExecutionListenerTests { } @Test + public void beforeTestMethodWithBeforeTransactionDeclaredAsInterfaceDefaultMethod() throws Exception { + assertBeforeTestMethod(BeforeTransactionDeclaredAsInterfaceDefaultMethodTestCase.class); + } + + @Test + public void afterTestMethodWithAfterTransactionDeclaredAsInterfaceDefaultMethod() throws Exception { + assertAfterTestMethod(AfterTransactionDeclaredAsInterfaceDefaultMethodTestCase.class); + } + + @Test public void retrieveConfigurationAttributesWithMissingTransactionConfiguration() throws Exception { assertTransactionConfigurationAttributes(MissingTransactionConfigurationTestCase.class, "", true); } @@ -344,6 +355,16 @@ public class TransactionalTestExecutionListenerTests { } @Test + public void isRollbackWithClassLevelRollbackWithExplicitValueOnTestInterface() throws Exception { + assertIsRollback(ClassLevelRollbackWithExplicitValueOnTestInterfaceTestCase.class, false); + } + + @Test + public void isRollbackWithClassLevelRollbackViaMetaAnnotationOnTestInterface() throws Exception { + assertIsRollback(ClassLevelRollbackViaMetaAnnotationOnTestInterfaceTestCase.class, false); + } + + @Test public void isRollbackWithRollbackAndTransactionConfigurationDeclaredAtClassLevel() throws Exception { Class<?> clazz = ClassLevelRollbackAndTransactionConfigurationTestCase.class; BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz); @@ -388,17 +409,35 @@ public class TransactionalTestExecutionListenerTests { String transactionManager() default "metaTxMgr"; } - private static abstract class Invocable { + private interface Invocable { + + void invoked(boolean invoked); + + boolean invoked(); + } + + private static class AbstractInvocable implements Invocable { boolean invoked = false; + + + @Override + public void invoked(boolean invoked) { + this.invoked = invoked; + } + + @Override + public boolean invoked() { + return this.invoked; + } } @Transactional - static class TransactionalDeclaredOnClassLocallyTestCase extends Invocable { + static class TransactionalDeclaredOnClassLocallyTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } public void transactionalTest() { @@ -406,11 +445,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class TransactionalDeclaredOnMethodLocallyTestCase extends Invocable { + static class TransactionalDeclaredOnMethodLocallyTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } @Transactional @@ -424,11 +463,11 @@ public class TransactionalTestExecutionListenerTests { } @MetaTransactional - static class TransactionalDeclaredOnClassViaMetaAnnotationTestCase extends Invocable { + static class TransactionalDeclaredOnClassViaMetaAnnotationTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } public void transactionalTest() { @@ -436,11 +475,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class TransactionalDeclaredOnMethodViaMetaAnnotationTestCase extends Invocable { + static class TransactionalDeclaredOnMethodViaMetaAnnotationTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } @MetaTransactional @@ -454,11 +493,11 @@ public class TransactionalTestExecutionListenerTests { } @MetaTxWithOverride(propagation = NOT_SUPPORTED) - static class TransactionalDeclaredOnClassViaMetaAnnotationWithOverrideTestCase extends Invocable { + static class TransactionalDeclaredOnClassViaMetaAnnotationWithOverrideTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } public void transactionalTest() { @@ -466,11 +505,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class TransactionalDeclaredOnMethodViaMetaAnnotationWithOverrideTestCase extends Invocable { + static class TransactionalDeclaredOnMethodViaMetaAnnotationWithOverrideTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } @MetaTxWithOverride(propagation = NOT_SUPPORTED) @@ -483,11 +522,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class BeforeTransactionDeclaredLocallyTestCase extends Invocable { + static class BeforeTransactionDeclaredLocallyTestCase extends AbstractInvocable { @BeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } @Transactional @@ -500,11 +539,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class BeforeTransactionDeclaredViaMetaAnnotationTestCase extends Invocable { + static class BeforeTransactionDeclaredViaMetaAnnotationTestCase extends AbstractInvocable { @MetaBeforeTransaction public void beforeTransaction() { - invoked = true; + invoked(true); } @Transactional @@ -517,11 +556,11 @@ public class TransactionalTestExecutionListenerTests { } } - static class AfterTransactionDeclaredLocallyTestCase extends Invocable { + static class AfterTransactionDeclaredLocallyTestCase extends AbstractInvocable { @AfterTransaction public void afterTransaction() { - invoked = true; + invoked(true); } @Transactional @@ -534,12 +573,54 @@ public class TransactionalTestExecutionListenerTests { } } - static class AfterTransactionDeclaredViaMetaAnnotationTestCase extends Invocable { + static class AfterTransactionDeclaredViaMetaAnnotationTestCase extends AbstractInvocable { @MetaAfterTransaction public void afterTransaction() { - invoked = true; + invoked(true); + } + + @Transactional + public void transactionalTest() { + /* no-op */ + } + + public void nonTransactionalTest() { + /* no-op */ + } + } + + interface BeforeTransactionInterface extends Invocable { + + @BeforeTransaction + default void beforeTransaction() { + invoked(true); } + } + + interface AfterTransactionInterface extends Invocable { + + @AfterTransaction + default void afterTransaction() { + invoked(true); + } + } + + static class BeforeTransactionDeclaredAsInterfaceDefaultMethodTestCase extends AbstractInvocable + implements BeforeTransactionInterface { + + @Transactional + public void transactionalTest() { + /* no-op */ + } + + public void nonTransactionalTest() { + /* no-op */ + } + } + + static class AfterTransactionDeclaredAsInterfaceDefaultMethodTestCase extends AbstractInvocable + implements AfterTransactionInterface { @Transactional public void transactionalTest() { @@ -642,4 +723,25 @@ public class TransactionalTestExecutionListenerTests { } } + @Rollback(false) + interface RollbackFalseTestInterface { + } + + static class ClassLevelRollbackWithExplicitValueOnTestInterfaceTestCase implements RollbackFalseTestInterface { + + public void test() { + } + } + + @Commit + interface RollbackFalseViaMetaAnnotationTestInterface { + } + + static class ClassLevelRollbackViaMetaAnnotationOnTestInterfaceTestCase + implements RollbackFalseViaMetaAnnotationTestInterface { + + public void test() { + } + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java index 0353a870..55201245 100644 --- a/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -38,11 +38,12 @@ import static org.springframework.test.context.web.ServletTestExecutionListener. * Unit tests for {@link ServletTestExecutionListener}. * * @author Sam Brannen + * @author Phillip Webb * @since 3.2.6 */ public class ServletTestExecutionListenerTests { - private static final String SET_UP_OUTSIDE_OF_STEL = "SET_UP_OUTSIDE_OF_STEL"; + private static final String SET_UP_OUTSIDE_OF_STEL = "setUpOutsideOfStel"; private final WebApplicationContext wac = mock(WebApplicationContext.class); private final MockServletContext mockServletContext = new MockServletContext(); @@ -50,30 +51,6 @@ public class ServletTestExecutionListenerTests { private final ServletTestExecutionListener listener = new ServletTestExecutionListener(); - private void assertAttributesAvailable() { - assertNotNull("request attributes should be available", RequestContextHolder.getRequestAttributes()); - } - - private void assertAttributesNotAvailable() { - assertNull("request attributes should not be available", RequestContextHolder.getRequestAttributes()); - } - - private void assertAttributeExists() { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - assertNotNull("request attributes should exist", requestAttributes); - Object setUpOutsideOfStel = requestAttributes.getAttribute(SET_UP_OUTSIDE_OF_STEL, - RequestAttributes.SCOPE_REQUEST); - assertNotNull(SET_UP_OUTSIDE_OF_STEL + " should exist as a request attribute", setUpOutsideOfStel); - } - - private void assertAttributeDoesNotExist() { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - assertNotNull("request attributes should exist", requestAttributes); - Object setUpOutsideOfStel = requestAttributes.getAttribute(SET_UP_OUTSIDE_OF_STEL, - RequestAttributes.SCOPE_REQUEST); - assertNull(SET_UP_OUTSIDE_OF_STEL + " should NOT exist as a request attribute", setUpOutsideOfStel); - } - @Before public void setUp() { given(wac.getServletContext()).willReturn(mockServletContext); @@ -86,7 +63,7 @@ public class ServletTestExecutionListenerTests { request.setAttribute(SET_UP_OUTSIDE_OF_STEL, "true"); RequestContextHolder.setRequestAttributes(servletWebRequest); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); } @Test @@ -95,16 +72,16 @@ public class ServletTestExecutionListenerTests { given(testContext.getApplicationContext()).willReturn(mock(ApplicationContext.class)); listener.beforeTestClass(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); listener.prepareTestInstance(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); listener.beforeTestMethod(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); listener.afterTestMethod(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); } @Test @@ -112,22 +89,22 @@ public class ServletTestExecutionListenerTests { BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(LegacyWebTestCase.class); RequestContextHolder.resetRequestAttributes(); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); listener.beforeTestClass(testContext); listener.prepareTestInstance(testContext); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); verify(testContext, times(0)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); given(testContext.getAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE)).willReturn(null); listener.beforeTestMethod(testContext); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); verify(testContext, times(0)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); listener.afterTestMethod(testContext); verify(testContext, times(1)).removeAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); } @Test @@ -135,21 +112,21 @@ public class ServletTestExecutionListenerTests { BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(LegacyWebTestCase.class); listener.beforeTestClass(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); listener.prepareTestInstance(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); verify(testContext, times(0)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); given(testContext.getAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE)).willReturn(null); listener.beforeTestMethod(testContext); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); verify(testContext, times(0)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); given(testContext.getAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE)).willReturn(null); listener.afterTestMethod(testContext); verify(testContext, times(1)).removeAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE); - assertAttributeExists(); + assertSetUpOutsideOfStelAttributeExists(); } @Test @@ -158,7 +135,7 @@ public class ServletTestExecutionListenerTests { RequestContextHolder.resetRequestAttributes(); listener.beforeTestClass(testContext); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); assertWebAppConfigTestCase(); } @@ -168,28 +145,70 @@ public class ServletTestExecutionListenerTests { BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(AtWebAppConfigWebTestCase.class); listener.beforeTestClass(testContext); - assertAttributesAvailable(); + assertRequestAttributesExist(); assertWebAppConfigTestCase(); } + /** + * @since 4.3 + */ + @Test + public void activateListenerWithoutExistingRequestAttributes() throws Exception { + BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(NoAtWebAppConfigWebTestCase.class); + given(testContext.getAttribute(ServletTestExecutionListener.ACTIVATE_LISTENER)).willReturn(true); + + RequestContextHolder.resetRequestAttributes(); + listener.beforeTestClass(testContext); + assertRequestAttributesDoNotExist(); + + assertWebAppConfigTestCase(); + } + + + private RequestAttributes assertRequestAttributesExist() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + assertNotNull("request attributes should exist", requestAttributes); + return requestAttributes; + } + + private void assertRequestAttributesDoNotExist() { + assertNull("request attributes should not exist", RequestContextHolder.getRequestAttributes()); + } + + private void assertSetUpOutsideOfStelAttributeExists() { + RequestAttributes requestAttributes = assertRequestAttributesExist(); + Object setUpOutsideOfStel = requestAttributes.getAttribute(SET_UP_OUTSIDE_OF_STEL, + RequestAttributes.SCOPE_REQUEST); + assertNotNull(SET_UP_OUTSIDE_OF_STEL + " should exist as a request attribute", setUpOutsideOfStel); + } + + private void assertSetUpOutsideOfStelAttributeDoesNotExist() { + RequestAttributes requestAttributes = assertRequestAttributesExist(); + Object setUpOutsideOfStel = requestAttributes.getAttribute(SET_UP_OUTSIDE_OF_STEL, + RequestAttributes.SCOPE_REQUEST); + assertNull(SET_UP_OUTSIDE_OF_STEL + " should NOT exist as a request attribute", setUpOutsideOfStel); + } + private void assertWebAppConfigTestCase() throws Exception { listener.prepareTestInstance(testContext); - assertAttributeDoesNotExist(); + assertRequestAttributesExist(); + assertSetUpOutsideOfStelAttributeDoesNotExist(); verify(testContext, times(1)).setAttribute(POPULATED_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); verify(testContext, times(1)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); given(testContext.getAttribute(POPULATED_REQUEST_CONTEXT_HOLDER_ATTRIBUTE)).willReturn(Boolean.TRUE); given(testContext.getAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE)).willReturn(Boolean.TRUE); listener.beforeTestMethod(testContext); - assertAttributeDoesNotExist(); + assertRequestAttributesExist(); + assertSetUpOutsideOfStelAttributeDoesNotExist(); verify(testContext, times(1)).setAttribute(POPULATED_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); verify(testContext, times(1)).setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE); listener.afterTestMethod(testContext); verify(testContext).removeAttribute(POPULATED_REQUEST_CONTEXT_HOLDER_ATTRIBUTE); verify(testContext).removeAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE); - assertAttributesNotAvailable(); + assertRequestAttributesDoNotExist(); } @@ -200,4 +219,7 @@ public class ServletTestExecutionListenerTests { static class AtWebAppConfigWebTestCase { } + static class NoAtWebAppConfigWebTestCase { + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/web/WebAppConfigurationBootstrapWithTests.java b/spring-test/src/test/java/org/springframework/test/context/web/WebAppConfigurationBootstrapWithTests.java new file mode 100644 index 00000000..ad03bb81 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/web/WebAppConfigurationBootstrapWithTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2016 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.test.context.web; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfigurationBootstrapWithTests.CustomWebTestContextBootstrapper; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * JUnit-based integration tests that verify support for loading a + * {@link WebApplicationContext} with a custom {@link WebTestContextBootstrapper}. + * + * @author Sam Brannen + * @author Phillip Webb + * @since 4.3 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@WebAppConfiguration +@BootstrapWith(CustomWebTestContextBootstrapper.class) +public class WebAppConfigurationBootstrapWithTests { + + @Autowired + WebApplicationContext wac; + + + @Test + public void webApplicationContextIsLoaded() { + // from: src/test/webapp/resources/Spring.js + Resource resource = wac.getResource("/resources/Spring.js"); + assertNotNull(resource); + assertTrue(resource.exists()); + } + + + @Configuration + static class Config { + } + + /** + * Custom {@link WebTestContextBootstrapper} that requires {@code @WebAppConfiguration} + * but hard codes the resource base path. + */ + static class CustomWebTestContextBootstrapper extends WebTestContextBootstrapper { + + @Override + protected MergedContextConfiguration processMergedContextConfiguration(MergedContextConfiguration mergedConfig) { + return new WebMergedContextConfiguration(mergedConfig, "src/test/webapp"); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/web/socket/WebSocketServletServerContainerFactoryBeanTests.java b/spring-test/src/test/java/org/springframework/test/context/web/socket/WebSocketServletServerContainerFactoryBeanTests.java new file mode 100644 index 00000000..f35b87f9 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/web/socket/WebSocketServletServerContainerFactoryBeanTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2016 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.test.context.web.socket; + +import javax.websocket.server.ServerContainer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; + +import static org.junit.Assert.*; + +/** + * Integration tests that validate support for {@link ServletServerContainerFactoryBean} + * in conjunction with {@link WebAppConfiguration @WebAppConfiguration} and the + * Spring TestContext Framework. + * + * @author Sam Brannen + * @since 4.3.1 + */ +@RunWith(SpringRunner.class) +@WebAppConfiguration +public class WebSocketServletServerContainerFactoryBeanTests { + + @Autowired + ServerContainer serverContainer; + + + @Test + public void servletServerContainerFactoryBeanSupport() { + assertEquals(42, serverContainer.getDefaultMaxTextMessageBufferSize()); + } + + + @Configuration + @EnableWebSocket + static class WebSocketConfig { + + @Bean + ServletServerContainerFactoryBean createWebSocketContainer() { + ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); + container.setMaxTextMessageBufferSize(42); + return container; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java b/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java index 03db1d60..3416f215 100644 --- a/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -25,10 +25,13 @@ import java.lang.annotation.Target; import org.junit.Test; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor; +import org.springframework.test.util.MetaAnnotationUtils.UntypedAnnotationDescriptor; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @@ -112,10 +115,27 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorWithInheritedAnnotationOnInterface() throws Exception { // Note: @Transactional is inherited - assertEquals(InheritedAnnotationInterface.class, - findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class)); - assertNull(findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class)); + Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class); + + AnnotationDescriptor<Transactional> descriptor; + + descriptor = findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(InheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubSubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -130,9 +150,21 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorForNonInheritedAnnotationOnInterface() throws Exception { // Note: @Order is not inherited. - assertEquals(NonInheritedAnnotationInterface.class, - findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class)); + Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class); + + AnnotationDescriptor<Order> descriptor; + + descriptor = findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(SubNonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -158,7 +190,17 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorForClassWithMetaAnnotatedInterface() { - assertNull(findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class)); + Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, + Component.class); + + AnnotationDescriptor<Component> descriptor; + + descriptor = findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class); + assertNotNull(descriptor); + assertEquals(ClassWithMetaAnnotatedInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(Meta1.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + assertEquals(Meta1.class, descriptor.getComposedAnnotation().annotationType()); } @Test @@ -253,11 +295,27 @@ public class MetaAnnotationUtilsTests { @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesWithInheritedAnnotationOnInterface() throws Exception { // Note: @Transactional is inherited - assertEquals( - InheritedAnnotationInterface.class, - findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class)); - assertNull(findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class)); + Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(InheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubSubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -274,10 +332,21 @@ public class MetaAnnotationUtilsTests { @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnInterface() throws Exception { // Note: @Order is not inherited. - assertEquals( - NonInheritedAnnotationInterface.class, - findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class)); + Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(SubNonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -345,8 +414,18 @@ public class MetaAnnotationUtilsTests { @Test @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesForClassWithMetaAnnotatedInterface() { - assertNull(findAnnotationDescriptorForTypes(ClassWithMetaAnnotatedInterface.class, Service.class, - Component.class, Order.class, Transactional.class)); + Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, + Component.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(ClassWithMetaAnnotatedInterface.class, Service.class, + Component.class, Order.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(ClassWithMetaAnnotatedInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(Meta1.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + assertEquals(Meta1.class, descriptor.getComposedAnnotation().annotationType()); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java b/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java index fa692ed9..3ea39f9b 100644 --- a/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -22,9 +22,12 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.support.AopUtils; import org.springframework.test.util.subpackage.Component; import org.springframework.test.util.subpackage.LegacyEntity; import org.springframework.test.util.subpackage.Person; +import org.springframework.test.util.subpackage.PersonEntity; import org.springframework.test.util.subpackage.StaticFields; import static org.hamcrest.CoreMatchers.*; @@ -41,12 +44,14 @@ public class ReflectionTestUtilsTests { private static final Float PI = new Float((float) 22 / 7); - private final Person person = new Person(); + private final Person person = new PersonEntity(); private final Component component = new Component(); + private final LegacyEntity entity = new LegacyEntity(); + @Rule - public ExpectedException exception = ExpectedException.none(); + public final ExpectedException exception = ExpectedException.none(); @Before @@ -54,7 +59,6 @@ public class ReflectionTestUtilsTests { StaticFields.reset(); } - @Test public void setFieldWithNullTargetObject() throws Exception { exception.expect(IllegalArgumentException.class); @@ -106,6 +110,29 @@ public class ReflectionTestUtilsTests { @Test public void setFieldAndGetFieldForStandardUseCases() throws Exception { + assertSetFieldAndGetFieldBehavior(this.person); + } + + @Test + public void setFieldAndGetFieldViaJdkDynamicProxy() throws Exception { + ProxyFactory pf = new ProxyFactory(this.person); + pf.addInterface(Person.class); + Person proxy = (Person) pf.getProxy(); + assertTrue("Proxy is a JDK dynamic proxy", AopUtils.isJdkDynamicProxy(proxy)); + assertSetFieldAndGetFieldBehaviorForProxy(proxy, this.person); + } + + @Test + public void setFieldAndGetFieldViaCglibProxy() throws Exception { + ProxyFactory pf = new ProxyFactory(this.person); + pf.setProxyTargetClass(true); + Person proxy = (Person) pf.getProxy(); + assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy)); + assertSetFieldAndGetFieldBehaviorForProxy(proxy, this.person); + } + + private static void assertSetFieldAndGetFieldBehavior(Person person) { + // Set reflectively setField(person, "id", new Long(99), long.class); setField(person, "name", "Tom"); setField(person, "age", new Integer(42)); @@ -113,19 +140,33 @@ public class ReflectionTestUtilsTests { setField(person, "likesPets", Boolean.TRUE); setField(person, "favoriteNumber", PI, Number.class); + // Get reflectively + assertEquals(new Long(99), getField(person, "id")); + assertEquals("Tom", getField(person, "name")); + assertEquals(new Integer(42), getField(person, "age")); + assertEquals("blue", getField(person, "eyeColor")); + assertEquals(Boolean.TRUE, getField(person, "likesPets")); + assertEquals(PI, getField(person, "favoriteNumber")); + + // Get directly assertEquals("ID (private field in a superclass)", 99, person.getId()); assertEquals("name (protected field)", "Tom", person.getName()); assertEquals("age (private field)", 42, person.getAge()); assertEquals("eye color (package private field)", "blue", person.getEyeColor()); assertEquals("'likes pets' flag (package private boolean field)", true, person.likesPets()); assertEquals("'favorite number' (package field)", PI, person.getFavoriteNumber()); + } - assertEquals(new Long(99), getField(person, "id")); - assertEquals("Tom", getField(person, "name")); - assertEquals(new Integer(42), getField(person, "age")); - assertEquals("blue", getField(person, "eyeColor")); - assertEquals(Boolean.TRUE, getField(person, "likesPets")); - assertEquals(PI, getField(person, "favoriteNumber")); + private static void assertSetFieldAndGetFieldBehaviorForProxy(Person proxy, Person target) { + assertSetFieldAndGetFieldBehavior(proxy); + + // Get directly from Target + assertEquals("ID (private field in a superclass)", 99, target.getId()); + assertEquals("name (protected field)", "Tom", target.getName()); + assertEquals("age (private field)", 42, target.getAge()); + assertEquals("eye color (package private field)", "blue", target.getEyeColor()); + assertEquals("'likes pets' flag (package private boolean field)", true, target.likesPets()); + assertEquals("'favorite number' (package field)", PI, target.getFavoriteNumber()); } @Test @@ -163,17 +204,6 @@ public class ReflectionTestUtilsTests { setField(person, "likesPets", null, boolean.class); } - /** - * Verifies behavior requested in <a href="https://jira.spring.io/browse/SPR-9571">SPR-9571</a>. - */ - @Test - public void setFieldOnLegacyEntityWithSideEffectsInToString() { - String testCollaborator = "test collaborator"; - LegacyEntity entity = new LegacyEntity(); - setField(entity, "collaborator", testCollaborator, Object.class); - assertTrue(entity.toString().contains(testCollaborator)); - } - @Test public void setStaticFieldViaClass() throws Exception { setField(StaticFields.class, "publicField", "xxx"); @@ -359,4 +389,37 @@ public class ReflectionTestUtilsTests { invokeMethod(component, "configure", new Integer(42), "enigma", "baz", "quux"); } + @Test // SPR-14363 + public void getFieldOnLegacyEntityWithSideEffectsInToString() { + Object collaborator = getField(entity, "collaborator"); + assertNotNull(collaborator); + } + + @Test // SPR-9571 and SPR-14363 + public void setFieldOnLegacyEntityWithSideEffectsInToString() { + String testCollaborator = "test collaborator"; + setField(entity, "collaborator", testCollaborator, Object.class); + assertTrue(entity.toString().contains(testCollaborator)); + } + + @Test // SPR-14363 + public void invokeMethodOnLegacyEntityWithSideEffectsInToString() { + invokeMethod(entity, "configure", new Integer(42), "enigma"); + assertEquals("number should have been configured", new Integer(42), entity.getNumber()); + assertEquals("text should have been configured", "enigma", entity.getText()); + } + + @Test // SPR-14363 + public void invokeGetterMethodOnLegacyEntityWithSideEffectsInToString() { + Object collaborator = invokeGetterMethod(entity, "collaborator"); + assertNotNull(collaborator); + } + + @Test // SPR-14363 + public void invokeSetterMethodOnLegacyEntityWithSideEffectsInToString() { + String testCollaborator = "test collaborator"; + invokeSetterMethod(entity, "collaborator", testCollaborator); + assertTrue(entity.toString().contains(testCollaborator)); + } + } diff --git a/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntity.java b/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntity.java index 8c8ddfd4..72d4633f 100644 --- a/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntity.java +++ b/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -31,17 +31,41 @@ public class LegacyEntity { @Override public String toString() { - throw new RuntimeException( + throw new LegacyEntityException( "Invoking toString() on the default collaborator causes an undesirable side effect"); - }; + } }; + private Integer number; + private String text; + + + public void configure(Integer number, String text) { + this.number = number; + this.text = text; + } + + public Integer getNumber() { + return this.number; + } + + public String getText() { + return this.text; + } + + public Object getCollaborator() { + return this.collaborator; + } + + public void setCollaborator(Object collaborator) { + this.collaborator = collaborator; + } @Override public String toString() { return new ToStringCreator(this)// - .append("collaborator", this.collaborator)// - .toString(); + .append("collaborator", this.collaborator)// + .toString(); } } diff --git a/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntityException.java b/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntityException.java new file mode 100644 index 00000000..2318e90a --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/util/subpackage/LegacyEntityException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2016 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.test.util.subpackage; + +/** + * Exception thrown by a {@link LegacyEntity}. + * + * @author Sam Brannen + * @since 4.3.1 + */ +@SuppressWarnings("serial") +public class LegacyEntityException extends RuntimeException { + + public LegacyEntityException(String message) { + super(message); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java b/spring-test/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java index 3ff3d91d..4f34e2e8 100644 --- a/spring-test/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java +++ b/spring-test/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2011 the original author or authors. + * Copyright 2007-2016 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. @@ -28,11 +28,12 @@ public abstract class PersistentEntity { private long id; - public final long getId() { + public long getId() { return this.id; } - protected final void setId(long id) { + protected void setId(long id) { this.id = id; } + } diff --git a/spring-test/src/test/java/org/springframework/test/util/subpackage/Person.java b/spring-test/src/test/java/org/springframework/test/util/subpackage/Person.java index b89f5616..20177ed0 100644 --- a/spring-test/src/test/java/org/springframework/test/util/subpackage/Person.java +++ b/spring-test/src/test/java/org/springframework/test/util/subpackage/Person.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -16,85 +16,27 @@ package org.springframework.test.util.subpackage; -import org.springframework.core.style.ToStringCreator; - /** - * Concrete subclass of {@link PersistentEntity} representing a <em>person</em> - * entity; intended for use in unit tests. + * Interface representing a <em>person</em> entity; intended for use in unit tests. + * + * <p>The introduction of an interface is necessary in order to test support for + * JDK dynamic proxies. * * @author Sam Brannen - * @since 2.5 + * @since 4.3 */ -public class Person extends PersistentEntity { - - protected String name; - - private int age; - - String eyeColor; - - boolean likesPets = false; - - private Number favoriteNumber; - - - public final String getName() { - return this.name; - } - - @SuppressWarnings("unused") - private final void setName(final String name) { - this.name = name; - } - - public final int getAge() { - return this.age; - } - - protected final void setAge(final int age) { - this.age = age; - } - - public final String getEyeColor() { - return this.eyeColor; - } - - final void setEyeColor(final String eyeColor) { - this.eyeColor = eyeColor; - } - - public final boolean likesPets() { - return this.likesPets; - } - - protected final void setLikesPets(final boolean likesPets) { - this.likesPets = likesPets; - } - - public final Number getFavoriteNumber() { - return this.favoriteNumber; - } - - protected final void setFavoriteNumber(Number favoriteNumber) { - this.favoriteNumber = favoriteNumber; - } - - @Override - public String toString() { - return new ToStringCreator(this) +public interface Person { - .append("id", this.getId()) + long getId(); - .append("name", this.name) + String getName(); - .append("age", this.age) + int getAge(); - .append("eyeColor", this.eyeColor) + String getEyeColor(); - .append("likesPets", this.likesPets) + boolean likesPets(); - .append("favoriteNumber", this.favoriteNumber) + Number getFavoriteNumber(); - .toString(); - } } diff --git a/spring-test/src/test/java/org/springframework/test/util/subpackage/PersonEntity.java b/spring-test/src/test/java/org/springframework/test/util/subpackage/PersonEntity.java new file mode 100644 index 00000000..1cdff47b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/util/subpackage/PersonEntity.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2016 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.test.util.subpackage; + +import org.springframework.core.style.ToStringCreator; + +/** + * Concrete subclass of {@link PersistentEntity} representing a <em>person</em> + * entity; intended for use in unit tests. + * + * @author Sam Brannen + * @since 2.5 + */ +public class PersonEntity extends PersistentEntity implements Person { + + protected String name; + + private int age; + + String eyeColor; + + boolean likesPets = false; + + private Number favoriteNumber; + + + public String getName() { + return this.name; + } + + @SuppressWarnings("unused") + private void setName(final String name) { + this.name = name; + } + + public int getAge() { + return this.age; + } + + protected void setAge(final int age) { + this.age = age; + } + + public String getEyeColor() { + return this.eyeColor; + } + + void setEyeColor(final String eyeColor) { + this.eyeColor = eyeColor; + } + + public boolean likesPets() { + return this.likesPets; + } + + protected void setLikesPets(final boolean likesPets) { + this.likesPets = likesPets; + } + + public Number getFavoriteNumber() { + return this.favoriteNumber; + } + + protected void setFavoriteNumber(Number favoriteNumber) { + this.favoriteNumber = favoriteNumber; + } + + @Override + public String toString() { + // @formatter:off + return new ToStringCreator(this) + .append("id", this.getId()) + .append("name", this.name) + .append("age", this.age) + .append("eyeColor", this.eyeColor) + .append("likesPets", this.likesPets) + .append("favoriteNumber", this.favoriteNumber) + .toString(); + // @formatter:on + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java b/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java new file mode 100644 index 00000000..aea4f2d8 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java @@ -0,0 +1,99 @@ +/* + * Copyright 2002-2016 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.test.web.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockAsyncClientHttpRequest; + +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.test.web.client.ExpectedCount.once; +import static org.springframework.test.web.client.ExpectedCount.times; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Unit tests for {@link DefaultRequestExpectation}. + * @author Rossen Stoyanchev + */ +public class DefaultRequestExpectationTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + + @Test + public void match() throws Exception { + RequestExpectation expectation = new DefaultRequestExpectation(once(), requestTo("/foo")); + expectation.match(createRequest(GET, "/foo")); + } + + @Test + public void matchWithFailedExpection() throws Exception { + RequestExpectation expectation = new DefaultRequestExpectation(once(), requestTo("/foo")); + expectation.andExpect(method(POST)); + + this.thrown.expectMessage("Unexpected HttpMethod expected:<POST> but was:<GET>"); + expectation.match(createRequest(GET, "/foo")); + } + + @Test + public void hasRemainingCount() throws Exception { + RequestExpectation expectation = new DefaultRequestExpectation(times(2), requestTo("/foo")); + expectation.andRespond(withSuccess()); + + expectation.createResponse(createRequest(GET, "/foo")); + assertTrue(expectation.hasRemainingCount()); + + expectation.createResponse(createRequest(GET, "/foo")); + assertFalse(expectation.hasRemainingCount()); + } + + @Test + public void isSatisfied() throws Exception { + RequestExpectation expectation = new DefaultRequestExpectation(times(2), requestTo("/foo")); + expectation.andRespond(withSuccess()); + + expectation.createResponse(createRequest(GET, "/foo")); + assertFalse(expectation.isSatisfied()); + + expectation.createResponse(createRequest(GET, "/foo")); + assertTrue(expectation.isSatisfied()); + } + + + + private ClientHttpRequest createRequest(HttpMethod method, String url) { + try { + return new MockAsyncClientHttpRequest(method, new URI(url)); + } + catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java b/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java deleted file mode 100644 index dfd3a714..00000000 --- a/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2014 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.test.web.client; - -import java.net.URI; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.http.HttpMethod; -import org.springframework.http.client.ClientHttpRequest; -import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.web.client.RestTemplate; - -import static org.junit.Assert.*; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; - -/** - * Tests for - * {@link org.springframework.test.web.client.MockMvcClientHttpRequestFactory}. - * - * @author Rossen Stoyanchev - */ -public class MockClientHttpRequestFactoryTests { - - private MockRestServiceServer server; - - private ClientHttpRequestFactory factory; - - - @Before - public void setup() { - RestTemplate restTemplate = new RestTemplate(); - this.server = MockRestServiceServer.createServer(restTemplate); - this.factory = restTemplate.getRequestFactory(); - } - - @Test - public void createRequest() throws Exception { - URI uri = new URI("/foo"); - ClientHttpRequest expected = (ClientHttpRequest) this.server.expect(anything()); - ClientHttpRequest actual = this.factory.createRequest(uri, HttpMethod.GET); - - assertSame(expected, actual); - assertEquals(uri, actual.getURI()); - assertEquals(HttpMethod.GET, actual.getMethod()); - } - - @Test - public void noFurtherRequestsExpected() throws Exception { - try { - this.factory.createRequest(new URI("/foo"), HttpMethod.GET); - } - catch (AssertionError error) { - assertEquals("No further requests expected: HTTP GET /foo", error.getMessage()); - } - } - - @Test - public void verifyZeroExpected() throws Exception { - this.server.verify(); - } - - @Test - public void verifyExpectedEqualExecuted() throws Exception { - this.server.expect(anything()); - this.server.expect(anything()); - - this.factory.createRequest(new URI("/foo"), HttpMethod.GET); - this.factory.createRequest(new URI("/bar"), HttpMethod.POST); - } - - @Test - public void verifyMoreExpected() throws Exception { - this.server.expect(anything()); - this.server.expect(anything()); - - this.factory.createRequest(new URI("/foo"), HttpMethod.GET); - - try { - this.server.verify(); - } - catch (AssertionError error) { - assertTrue(error.getMessage(), error.getMessage().contains("1 out of 2 were executed")); - } - } - -} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java new file mode 100644 index 00000000..ddf8b26f --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java @@ -0,0 +1,110 @@ +/* + * Copyright 2002-2016 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.test.web.client; + +import org.junit.Test; + +import org.springframework.test.web.client.MockRestServiceServer.MockRestServiceServerBuilder; +import org.springframework.web.client.RestTemplate; + +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Unit tests for {@link MockRestServiceServer}. + * @author Rossen Stoyanchev + */ +public class MockRestServiceServerTests { + + private RestTemplate restTemplate = new RestTemplate(); + + + @Test + public void buildMultipleTimes() throws Exception { + MockRestServiceServerBuilder builder = MockRestServiceServer.bindTo(this.restTemplate); + + MockRestServiceServer server = builder.build(); + server.expect(requestTo("/foo")).andRespond(withSuccess()); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + + server = builder.ignoreExpectOrder(true).build(); + server.expect(requestTo("/foo")).andRespond(withSuccess()); + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + + server = builder.build(); + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + server.verify(); + } + + @Test(expected = AssertionError.class) + public void exactExpectOrder() throws Exception { + MockRestServiceServer server = MockRestServiceServer.bindTo(this.restTemplate) + .ignoreExpectOrder(false).build(); + + server.expect(requestTo("/foo")).andRespond(withSuccess()); + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + } + + @Test + public void ignoreExpectOrder() throws Exception { + MockRestServiceServer server = MockRestServiceServer.bindTo(this.restTemplate) + .ignoreExpectOrder(true).build(); + + server.expect(requestTo("/foo")).andRespond(withSuccess()); + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + } + + @Test + public void resetAndReuseServer() throws Exception { + MockRestServiceServer server = MockRestServiceServer.bindTo(this.restTemplate).build(); + + server.expect(requestTo("/foo")).andRespond(withSuccess()); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + server.reset(); + + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + server.verify(); + } + + @Test + public void resetAndReuseServerWithUnorderedExpectationManager() throws Exception { + MockRestServiceServer server = MockRestServiceServer.bindTo(this.restTemplate) + .ignoreExpectOrder(true).build(); + + server.expect(requestTo("/foo")).andRespond(withSuccess()); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + server.reset(); + + server.expect(requestTo("/foo")).andRespond(withSuccess()); + server.expect(requestTo("/bar")).andRespond(withSuccess()); + this.restTemplate.getForObject("/bar", Void.class); + this.restTemplate.getForObject("/foo", Void.class); + server.verify(); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/SimpleRequestExpectationManagerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/SimpleRequestExpectationManagerTests.java new file mode 100644 index 00000000..d6f2b9cb --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/client/SimpleRequestExpectationManagerTests.java @@ -0,0 +1,173 @@ +/* + * Copyright 2002-2016 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.test.web.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockAsyncClientHttpRequest; + +import static org.junit.Assert.assertEquals; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.test.web.client.ExpectedCount.max; +import static org.springframework.test.web.client.ExpectedCount.min; +import static org.springframework.test.web.client.ExpectedCount.once; +import static org.springframework.test.web.client.ExpectedCount.times; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Unit tests for {@link SimpleRequestExpectationManager}. + * @author Rossen Stoyanchev + */ +public class SimpleRequestExpectationManagerTests { + + private SimpleRequestExpectationManager manager = new SimpleRequestExpectationManager(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + + @Test + public void unexpectedRequest() throws Exception { + try { + this.manager.validateRequest(createRequest(GET, "/foo")); + } + catch (AssertionError error) { + assertEquals("No further requests expected: HTTP GET /foo\n" + + "0 request(s) executed.\n", error.getMessage()); + } + } + + @Test + public void zeroExpectedRequests() throws Exception { + this.manager.verify(); + } + + @Test + public void sequentialRequests() throws Exception { + this.manager.expectRequest(once(), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(once(), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.verify(); + } + + @Test + public void sequentialRequestsTooMany() throws Exception { + this.manager.expectRequest(max(1), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(max(1), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("No further requests expected: HTTP GET /baz\n" + + "2 request(s) executed:\n" + + "GET /foo\n" + + "GET /bar\n"); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/baz")); + } + + @Test + public void sequentialRequestsTooFew() throws Exception { + this.manager.expectRequest(min(1), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(min(1), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("Further request(s) expected leaving 1 unsatisfied expectation(s).\n" + + "1 request(s) executed:\nGET /foo\n"); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.verify(); + } + + @Test + public void repeatedRequests() throws Exception { + this.manager.expectRequest(times(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(times(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.verify(); + } + + @Test + public void repeatedRequestsTooMany() throws Exception { + this.manager.expectRequest(max(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(max(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("No further requests expected: HTTP GET /foo\n" + + "4 request(s) executed:\n" + + "GET /foo\n" + + "GET /bar\n" + + "GET /foo\n" + + "GET /bar\n"); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + } + + @Test + public void repeatedRequestsTooFew() throws Exception { + this.manager.expectRequest(min(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(min(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("3 request(s) executed:\n" + + "GET /foo\n" + + "GET /bar\n" + + "GET /foo\n"); + + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.verify(); + } + + @Test + public void repeatedRequestsNotInOrder() throws Exception { + this.manager.expectRequest(times(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(times(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(times(2), requestTo("/baz")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("Unexpected HttpMethod expected:<GET> but was:<POST>"); + this.manager.validateRequest(createRequest(POST, "/foo")); + } + + + private ClientHttpRequest createRequest(HttpMethod method, String url) { + try { + return new MockAsyncClientHttpRequest(method, new URI(url)); + } + catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java new file mode 100644 index 00000000..163f3865 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java @@ -0,0 +1,133 @@ +/* + * Copyright 2002-2016 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.test.web.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockAsyncClientHttpRequest; + +import static org.junit.Assert.assertEquals; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.test.web.client.ExpectedCount.max; +import static org.springframework.test.web.client.ExpectedCount.min; +import static org.springframework.test.web.client.ExpectedCount.once; +import static org.springframework.test.web.client.ExpectedCount.times; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Unit tests for {@link UnorderedRequestExpectationManager}. + * @author Rossen Stoyanchev + */ +public class UnorderedRequestExpectationManagerTests { + + private UnorderedRequestExpectationManager manager = new UnorderedRequestExpectationManager(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + + @Test + public void unexpectedRequest() throws Exception { + try { + this.manager.validateRequest(createRequest(GET, "/foo")); + } + catch (AssertionError error) { + assertEquals("No further requests expected: HTTP GET /foo\n" + + "0 request(s) executed.\n", error.getMessage()); + } + } + + @Test + public void zeroExpectedRequests() throws Exception { + this.manager.verify(); + } + + @Test + public void multipleRequests() throws Exception { + this.manager.expectRequest(once(), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(once(), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.verify(); + } + + @Test + public void repeatedRequests() throws Exception { + this.manager.expectRequest(times(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(times(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.verify(); + } + + @Test + public void repeatedRequestsTooMany() throws Exception { + this.manager.expectRequest(max(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(max(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("No further requests expected: HTTP GET /foo\n" + + "4 request(s) executed:\n" + + "GET /bar\n" + + "GET /foo\n" + + "GET /bar\n" + + "GET /foo\n"); + + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/foo")); + } + + @Test + public void repeatedRequestsTooFew() throws Exception { + this.manager.expectRequest(min(2), requestTo("/foo")).andExpect(method(GET)).andRespond(withSuccess()); + this.manager.expectRequest(min(2), requestTo("/bar")).andExpect(method(GET)).andRespond(withSuccess()); + + this.thrown.expectMessage("3 request(s) executed:\n" + + "GET /bar\n" + + "GET /foo\n" + + "GET /foo\n"); + + this.manager.validateRequest(createRequest(GET, "/bar")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.validateRequest(createRequest(GET, "/foo")); + this.manager.verify(); + } + + + private ClientHttpRequest createRequest(HttpMethod method, String url) { + try { + return new MockAsyncClientHttpRequest(method, new URI(url)); + } + catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/match/ContentRequestMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/client/match/ContentRequestMatchersTests.java index eada001d..de034c24 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/match/ContentRequestMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/match/ContentRequestMatchersTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -15,11 +15,15 @@ */ package org.springframework.test.web.client.match; +import java.nio.charset.Charset; + import org.junit.Before; import org.junit.Test; import org.springframework.http.MediaType; import org.springframework.mock.http.client.MockClientHttpRequest; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import static org.hamcrest.Matchers.*; @@ -32,11 +36,13 @@ public class ContentRequestMatchersTests { private MockClientHttpRequest request; + @Before public void setUp() { this.request = new MockClientHttpRequest(); } + @Test public void testContentType() throws Exception { this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON); @@ -45,14 +51,14 @@ public class ContentRequestMatchersTests { MockRestRequestMatchers.content().contentType(MediaType.APPLICATION_JSON).match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testContentTypeNoMatch1() throws Exception { this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON); MockRestRequestMatchers.content().contentType("application/xml").match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testContentTypeNoMatch2() throws Exception { this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON); @@ -66,7 +72,7 @@ public class ContentRequestMatchersTests { MockRestRequestMatchers.content().string("test").match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testStringNoMatch() throws Exception { this.request.getBody().write("test".getBytes()); @@ -81,7 +87,7 @@ public class ContentRequestMatchersTests { MockRestRequestMatchers.content().bytes(content).match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testBytesNoMatch() throws Exception { this.request.getBody().write("test".getBytes()); @@ -89,6 +95,22 @@ public class ContentRequestMatchersTests { } @Test + public void testFormData() throws Exception { + String contentType = "application/x-www-form-urlencoded;charset=UTF-8"; + String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3"; + + this.request.getHeaders().setContentType(MediaType.parseMediaType(contentType)); + this.request.getBody().write(body.getBytes(Charset.forName("UTF-8"))); + + MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); + map.add("name 1", "value 1"); + map.add("name 2", "value A"); + map.add("name 2", "value B"); + map.add("name 3", null); + MockRestRequestMatchers.content().formData(map).match(this.request); + } + + @Test public void testXml() throws Exception { String content = "<foo><bar>baz</bar><bar>bazz</bar></foo>"; this.request.getBody().write(content.getBytes()); @@ -96,7 +118,7 @@ public class ContentRequestMatchersTests { MockRestRequestMatchers.content().xml(content).match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testXmlNoMatch() throws Exception { this.request.getBody().write("<foo>11</foo>".getBytes()); @@ -111,7 +133,7 @@ public class ContentRequestMatchersTests { MockRestRequestMatchers.content().node(hasXPath("/foo/bar")).match(this.request); } - @Test(expected=AssertionError.class) + @Test(expected = AssertionError.class) public void testNodeMatcherNoMatch() throws Exception { String content = "<foo><bar>baz</bar></foo>"; this.request.getBody().write(content.getBytes()); diff --git a/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java index 787020d6..58cad79c 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/match/MockRestRequestMatchersTests.java @@ -91,7 +91,6 @@ public class MockRestRequestMatchersTests { MockRestRequestMatchers.header("foo", "bad").match(this.request); } - @SuppressWarnings("unchecked") @Test public void headerContains() throws Exception { this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); @@ -99,13 +98,11 @@ public class MockRestRequestMatchersTests { MockRestRequestMatchers.header("foo", containsString("ba")).match(this.request); } - @SuppressWarnings("unchecked") @Test(expected = AssertionError.class) public void headerContainsWithMissingHeader() throws Exception { MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request); } - @SuppressWarnings("unchecked") @Test(expected = AssertionError.class) public void headerContainsWithMissingValue() throws Exception { this.request.getHeaders().put("foo", Arrays.asList("bar", "baz")); diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java index 73b17cb5..091b64d5 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.test.web.client.samples; -import org.junit.Before; import org.junit.Test; import org.springframework.core.io.ClassPathResource; @@ -29,6 +29,7 @@ import org.springframework.util.concurrent.ListenableFuture; import org.springframework.web.client.AsyncRestTemplate; import static org.junit.Assert.*; +import static org.springframework.test.web.client.ExpectedCount.manyTimes; import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; import static org.springframework.test.web.client.response.MockRestResponseCreators.*; @@ -39,20 +40,14 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat * code. * * @author Rossen Stoyanchev + * @since 4.1 */ public class SampleAsyncTests { - private MockRestServiceServer mockServer; - - private AsyncRestTemplate restTemplate; + private final AsyncRestTemplate restTemplate = new AsyncRestTemplate(); + private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate); - @Before - public void setup() { - this.restTemplate = new AsyncRestTemplate(); - this.mockServer = MockRestServiceServer.createServer(this.restTemplate); - - } @Test public void performGet() throws Exception { @@ -63,7 +58,8 @@ public class SampleAsyncTests { .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); @SuppressWarnings("unused") - ListenableFuture<ResponseEntity<Person>> ludwig = restTemplate.getForEntity("/composers/{id}", Person.class, 42); + ListenableFuture<ResponseEntity<Person>> ludwig = + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); // We are only validating the request. The response is mocked out. // person.getName().equals("Ludwig van Beethoven") @@ -73,19 +69,26 @@ public class SampleAsyncTests { } @Test - public void performGetAsync() throws Exception { + public void performGetManyTimes() throws Exception { String responseBody = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}"; - this.mockServer.expect(requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) + this.mockServer.expect(manyTimes(), requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); @SuppressWarnings("unused") - ListenableFuture<ResponseEntity<Person>> ludwig = restTemplate.getForEntity("/composers/{id}", Person.class, 42); + ListenableFuture<ResponseEntity<Person>> ludwig = + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); + // We are only validating the request. The response is mocked out. // person.getName().equals("Ludwig van Beethoven") // person.getDouble().equals(1.6035) + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); + this.mockServer.verify(); } @@ -98,7 +101,8 @@ public class SampleAsyncTests { .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); @SuppressWarnings("unused") - ListenableFuture<ResponseEntity<Person>> ludwig = restTemplate.getForEntity("/composers/{id}", Person.class, 42); + ListenableFuture<ResponseEntity<Person>> ludwig = + this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); // hotel.getId() == 42 // hotel.getName().equals("Holiday Inn") @@ -132,7 +136,8 @@ public class SampleAsyncTests { this.mockServer.verify(); } catch (AssertionError error) { - assertTrue(error.getMessage(), error.getMessage().contains("2 out of 4 were executed")); + assertTrue(error.getMessage(), error.getMessage().contains("2 unsatisfied expectation(s)")); } } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleTests.java index d3fc4823..6d5c7452 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleTests.java @@ -27,6 +27,7 @@ import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.client.ExpectedCount.manyTimes; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; @@ -48,7 +49,7 @@ public class SampleTests { @Before public void setup() { this.restTemplate = new RestTemplate(); - this.mockServer = MockRestServiceServer.createServer(this.restTemplate); + this.mockServer = MockRestServiceServer.bindTo(this.restTemplate).ignoreExpectOrder(true).build(); } @Test @@ -60,7 +61,7 @@ public class SampleTests { .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); @SuppressWarnings("unused") - Person ludwig = restTemplate.getForObject("/composers/{id}", Person.class, 42); + Person ludwig = this.restTemplate.getForObject("/composers/{id}", Person.class, 42); // We are only validating the request. The response is mocked out. // hotel.getId() == 42 @@ -70,6 +71,28 @@ public class SampleTests { } @Test + public void performGetManyTimes() throws Exception { + + String responseBody = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}"; + + this.mockServer.expect(manyTimes(), requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); + + @SuppressWarnings("unused") + Person ludwig = this.restTemplate.getForObject("/composers/{id}", Person.class, 42); + + // We are only validating the request. The response is mocked out. + // hotel.getId() == 42 + // hotel.getName().equals("Holiday Inn") + + this.restTemplate.getForObject("/composers/{id}", Person.class, 42); + this.restTemplate.getForObject("/composers/{id}", Person.class, 42); + this.restTemplate.getForObject("/composers/{id}", Person.class, 42); + + this.mockServer.verify(); + } + + @Test public void performGetWithResponseBodyFromFile() throws Exception { Resource responseBody = new ClassPathResource("ludwig.json", this.getClass()); @@ -78,7 +101,7 @@ public class SampleTests { .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); @SuppressWarnings("unused") - Person ludwig = restTemplate.getForObject("/composers/{id}", Person.class, 42); + Person ludwig = this.restTemplate.getForObject("/composers/{id}", Person.class, 42); // hotel.getId() == 42 // hotel.getName().equals("Holiday Inn") @@ -102,17 +125,18 @@ public class SampleTests { .andRespond(withSuccess("8", MediaType.TEXT_PLAIN)); @SuppressWarnings("unused") - String result = this.restTemplate.getForObject("/number", String.class); - // result == "1" + String result1 = this.restTemplate.getForObject("/number", String.class); + // result1 == "1" - result = this.restTemplate.getForObject("/number", String.class); + @SuppressWarnings("unused") + String result2 = this.restTemplate.getForObject("/number", String.class); // result == "2" try { this.mockServer.verify(); } catch (AssertionError error) { - assertTrue(error.getMessage(), error.getMessage().contains("2 out of 4 were executed")); + assertTrue(error.getMessage(), error.getMessage().contains("2 unsatisfied expectation(s)")); } } } diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/HeaderRequestMatchersIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/HeaderRequestMatchersIntegrationTests.java index 7ffb5eb9..1b56ffa2 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/HeaderRequestMatchersIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/HeaderRequestMatchersIntegrationTests.java @@ -71,7 +71,6 @@ public class HeaderRequestMatchersIntegrationTests { this.mockServer.verify(); } - @SuppressWarnings("unchecked") @Test public void testStringContains() throws Exception { diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java index beab7668..bf347eed 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java @@ -129,8 +129,7 @@ public class DelegatingWebConnectionTests { WebClient webClient = new WebClient(); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(TestController.class).build(); - MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc); - mockConnection.setWebClient(webClient); + MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc, webClient); WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*"); WebConnection httpConnection = new HttpWebConnection(webClient); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java index ddf68306..4c7f9cb5 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2015 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. @@ -16,7 +16,6 @@ package org.springframework.test.web.servlet.htmlunit; -import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; @@ -28,11 +27,9 @@ import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; -import com.gargoylesoftware.htmlunit.HttpMethod; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.WebRequest; -import com.gargoylesoftware.htmlunit.util.NameValuePair; +import org.apache.commons.io.IOUtils; import org.apache.http.auth.UsernamePasswordCredentials; + import org.junit.Before; import org.junit.Test; @@ -42,12 +39,16 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.FileCopyUtils; -import static java.util.Arrays.*; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.util.NameValuePair; + +import static java.util.Arrays.asList; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.junit.Assert.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; /** * Unit tests for {@link HtmlUnitRequestBuilder}. @@ -76,6 +77,7 @@ public class HtmlUnitRequestBuilderTests { requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); } + // --- constructor @Test(expected = IllegalArgumentException.class) public void constructorNullSessions() { @@ -92,6 +94,8 @@ public class HtmlUnitRequestBuilderTests { new HtmlUnitRequestBuilder(sessions, webClient, null); } + // --- buildRequest + @Test @SuppressWarnings("deprecation") public void buildRequestBasicAuth() { @@ -241,8 +245,7 @@ public class HtmlUnitRequestBuilderTests { MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(FileCopyUtils.copyToString(new InputStreamReader(actualRequest.getInputStream(), "ISO-8859-1")), - equalTo(content)); + assertThat(IOUtils.toString(actualRequest.getInputStream()), equalTo(content)); } @Test @@ -408,7 +411,8 @@ public class HtmlUnitRequestBuilderTests { assertThat(actualRequest.getParameter("name"), equalTo("value")); } - @Test // SPR-14177 + // SPR-14177 + @Test public void buildRequestParameterMapDecodesParameterName() throws Exception { webRequest.setUrl(new URL("http://example.com/example/?row%5B0%5D=value")); @@ -561,7 +565,7 @@ public class HtmlUnitRequestBuilderTests { MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(FileCopyUtils.copyToString(actualRequest.getReader()), equalTo(expectedBody)); + assertThat(IOUtils.toString(actualRequest.getReader()), equalTo(expectedBody)); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcConnectionBuilderSupportTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcConnectionBuilderSupportTests.java index c89f4f40..303f5af9 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcConnectionBuilderSupportTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcConnectionBuilderSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -20,6 +20,11 @@ import java.io.IOException; import java.net.URL; import javax.servlet.http.HttpServletRequest; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebConnection; +import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.WebResponse; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,20 +41,18 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import com.gargoylesoftware.htmlunit.WebConnection; -import com.gargoylesoftware.htmlunit.WebRequest; -import com.gargoylesoftware.htmlunit.WebResponse; - import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * Integration tests for {@link MockMvcWebConnectionBuilderSupport}. * * @author Rob Winch + * @author Rossen Stoyanchev * @since 4.2 */ @RunWith(SpringJUnit4ClassRunner.class) @@ -58,93 +61,85 @@ import static org.mockito.Mockito.mock; @SuppressWarnings("rawtypes") public class MockMvcConnectionBuilderSupportTests { - private final WebConnection delegateConnection = mock(WebConnection.class); + private final WebClient client = mock(WebClient.class); + + private MockMvcWebConnectionBuilderSupport builder; @Autowired private WebApplicationContext wac; - private MockMvc mockMvc; - - private WebConnection connection; @Before public void setup() { - mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); - - connection = new MockMvcWebConnectionBuilderSupport(mockMvc){} - .createConnection(delegateConnection); + when(this.client.getWebConnection()).thenReturn(mock(WebConnection.class)); + this.builder = new MockMvcWebConnectionBuilderSupport(this.wac) {}; } + @Test(expected = IllegalArgumentException.class) public void constructorMockMvcNull() { - new MockMvcWebConnectionBuilderSupport((MockMvc)null){}; + new MockMvcWebConnectionBuilderSupport((MockMvc) null){}; } @Test(expected = IllegalArgumentException.class) public void constructorContextNull() { - new MockMvcWebConnectionBuilderSupport((WebApplicationContext)null){}; + new MockMvcWebConnectionBuilderSupport((WebApplicationContext) null){}; } @Test public void context() throws Exception { - connection = new MockMvcWebConnectionBuilderSupport(wac) {} - .createConnection(delegateConnection); + WebConnection conn = this.builder.createConnection(this.client); - assertMvcProcessed("http://localhost/"); - assertDelegateProcessed("http://example.com/"); + assertMockMvcUsed(conn, "http://localhost/"); + assertMockMvcNotUsed(conn, "http://example.com/"); } @Test public void mockMvc() throws Exception { - assertMvcProcessed("http://localhost/"); - assertDelegateProcessed("http://example.com/"); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + WebConnection conn = new MockMvcWebConnectionBuilderSupport(mockMvc) {}.createConnection(this.client); + + assertMockMvcUsed(conn, "http://localhost/"); + assertMockMvcNotUsed(conn, "http://example.com/"); } @Test public void mockMvcExampleDotCom() throws Exception { - connection = new MockMvcWebConnectionBuilderSupport(wac) {} - .useMockMvcForHosts("example.com") - .createConnection(delegateConnection); + WebConnection conn = this.builder.useMockMvcForHosts("example.com").createConnection(this.client); - assertMvcProcessed("http://localhost/"); - assertMvcProcessed("http://example.com/"); - assertDelegateProcessed("http://other.com/"); + assertMockMvcUsed(conn, "http://localhost/"); + assertMockMvcUsed(conn, "http://example.com/"); + assertMockMvcNotUsed(conn, "http://other.com/"); } @Test public void mockMvcAlwaysUseMockMvc() throws Exception { - connection = new MockMvcWebConnectionBuilderSupport(wac) {} - .alwaysUseMockMvc() - .createConnection(delegateConnection); - - assertMvcProcessed("http://other.com/"); + WebConnection conn = this.builder.alwaysUseMockMvc().createConnection(this.client); + assertMockMvcUsed(conn, "http://other.com/"); } @Test public void defaultContextPathEmpty() throws Exception { - connection = new MockMvcWebConnectionBuilderSupport(wac) {} - .createConnection(delegateConnection); - - assertThat(getWebResponse("http://localhost/abc").getContentAsString(), equalTo("")); + WebConnection conn = this.builder.createConnection(this.client); + assertThat(getResponse(conn, "http://localhost/abc").getContentAsString(), equalTo("")); } @Test public void defaultContextPathCustom() throws Exception { - connection = new MockMvcWebConnectionBuilderSupport(wac) {} - .contextPath("/abc").createConnection(delegateConnection); - - assertThat(getWebResponse("http://localhost/abc/def").getContentAsString(), equalTo("/abc")); + WebConnection conn = this.builder.contextPath("/abc").createConnection(this.client); + assertThat(getResponse(conn, "http://localhost/abc/def").getContentAsString(), equalTo("/abc")); } - private void assertMvcProcessed(String url) throws Exception { - assertThat(getWebResponse(url), notNullValue()); + + private void assertMockMvcUsed(WebConnection connection, String url) throws Exception { + assertThat(getResponse(connection, url), notNullValue()); } - private void assertDelegateProcessed(String url) throws Exception { - assertThat(getWebResponse(url), nullValue()); + private void assertMockMvcNotUsed(WebConnection connection, String url) throws Exception { + assertThat(getResponse(connection, url), nullValue()); } - private WebResponse getWebResponse(String url) throws IOException { + private WebResponse getResponse(WebConnection connection, String url) throws IOException { return connection.getResponse(new WebRequest(new URL(url))); } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java index a7473c18..79a6af18 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java @@ -19,10 +19,13 @@ package org.springframework.test.web.servlet.htmlunit; import java.io.IOException; import java.net.URL; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebResponse; +import com.gargoylesoftware.htmlunit.util.Cookie; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,13 +33,17 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -49,9 +56,10 @@ import static org.junit.Assert.*; * * @author Rob Winch * @author Sam Brannen + * @author Rossen Stoyanchev * @since 4.2 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @WebAppConfiguration public class MockMvcWebClientBuilderTests { @@ -61,8 +69,6 @@ public class MockMvcWebClientBuilderTests { private MockMvc mockMvc; - private WebClient webClient; - @Before public void setup() { @@ -82,31 +88,65 @@ public class MockMvcWebClientBuilderTests { @Test public void mockMvcSetupWithDefaultWebClientDelegate() throws Exception { - this.webClient = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build(); + WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build(); - assertMvcProcessed("http://localhost/test"); - Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); + assertMockMvcUsed(client, "http://localhost/test"); + Assume.group(TestGroup.PERFORMANCE, () -> assertMockMvcNotUsed(client, "http://example.com/")); } @Test public void mockMvcSetupWithCustomWebClientDelegate() throws Exception { WebClient otherClient = new WebClient(); - this.webClient = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).withDelegate(otherClient).build(); + WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).withDelegate(otherClient).build(); + + assertMockMvcUsed(client, "http://localhost/test"); + Assume.group(TestGroup.PERFORMANCE, () -> assertMockMvcNotUsed(client, "http://example.com/")); + } + + @Test // SPR-14066 + public void cookieManagerShared() throws Exception { + this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build(); + WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build(); + + assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA")); + client.getCookieManager().addCookie(new Cookie("localhost", "cookie", "cookieManagerShared")); + assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("cookieManagerShared")); + } + + @Test // SPR-14265 + public void cookiesAreManaged() throws Exception { + this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build(); + WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build(); + + assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA")); + assertThat(postResponse(client, "http://localhost/?cookie=foo").getContentAsString(), equalTo("Set")); + assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("foo")); + assertThat(deleteResponse(client, "http://localhost/").getContentAsString(), equalTo("Delete")); + assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA")); + } + + private void assertMockMvcUsed(WebClient client, String url) throws Exception { + assertThat(getResponse(client, url).getContentAsString(), equalTo("mvc")); + } - assertMvcProcessed("http://localhost/test"); - Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); + private void assertMockMvcNotUsed(WebClient client, String url) throws Exception { + assertThat(getResponse(client, url).getContentAsString(), not(equalTo("mvc"))); } - private void assertMvcProcessed(String url) throws Exception { - assertThat(getWebResponse(url).getContentAsString(), equalTo("mvc")); + private WebResponse getResponse(WebClient client, String url) throws IOException { + return createResponse(client, new WebRequest(new URL(url))); } - private void assertDelegateProcessed(String url) throws Exception { - assertThat(getWebResponse(url).getContentAsString(), not(equalTo("mvc"))); + private WebResponse postResponse(WebClient client, String url) throws IOException { + return createResponse(client, new WebRequest(new URL(url), HttpMethod.POST)); } - private WebResponse getWebResponse(String url) throws IOException { - return this.webClient.getWebConnection().getResponse(new WebRequest(new URL(url))); + private WebResponse deleteResponse(WebClient client, String url) throws IOException { + return createResponse(client, new WebRequest(new URL(url), HttpMethod.DELETE)); + } + + private WebResponse createResponse(WebClient client, WebRequest request) throws IOException { + return client.getWebConnection().getResponse(request); } @@ -124,4 +164,29 @@ public class MockMvcWebClientBuilderTests { } } + @RestController + static class CookieController { + + static final String COOKIE_NAME = "cookie"; + + @RequestMapping(path = "/", produces = "text/plain") + String cookie(@CookieValue(name = COOKIE_NAME, defaultValue = "NA") String cookie) { + return cookie; + } + + @PostMapping(path = "/", produces = "text/plain") + String setCookie(@RequestParam String cookie, HttpServletResponse response) { + response.addCookie(new javax.servlet.http.Cookie(COOKIE_NAME, cookie)); + return "Set"; + } + + @DeleteMapping(path = "/", produces = "text/plain") + String deleteCookie(HttpServletResponse response) { + javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(COOKIE_NAME, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return "Delete"; + } + } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java index b74a22f2..1b3ba8ce 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java @@ -35,6 +35,7 @@ import static org.junit.Assert.*; * @author Rob Winch * @since 4.2 */ +@SuppressWarnings("deprecation") public class MockMvcWebConnectionTests { private final WebClient webClient = new WebClient(); @@ -49,7 +50,7 @@ public class MockMvcWebConnectionTests { @Test public void contextPathNull() throws IOException { - this.webClient.setWebConnection(new MockMvcWebConnection(this.mockMvc, null)); + this.webClient.setWebConnection(new MockMvcWebConnection(this.mockMvc, (String) null)); Page page = this.webClient.getPage("http://localhost/context/a"); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilderTests.java index f367153c..29c83115 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilderTests.java @@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.htmlunit; import java.net.URL; import java.util.List; +import javax.servlet.http.Cookie; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebResponse; @@ -95,16 +96,41 @@ public class MockWebResponseBuilderTests { public void buildResponseHeaders() throws Exception { this.response.addHeader("Content-Type", "text/html"); this.response.addHeader("X-Test", "value"); + Cookie cookie = new Cookie("cookieA", "valueA"); + cookie.setDomain("domain"); + cookie.setPath("/path"); + cookie.setMaxAge(1800); + cookie.setSecure(true); + cookie.setHttpOnly(true); + this.response.addCookie(cookie); WebResponse webResponse = this.responseBuilder.build(); List<NameValuePair> responseHeaders = webResponse.getResponseHeaders(); - assertThat(responseHeaders.size(), equalTo(2)); + assertThat(responseHeaders.size(), equalTo(3)); NameValuePair header = responseHeaders.get(0); assertThat(header.getName(), equalTo("Content-Type")); assertThat(header.getValue(), equalTo("text/html")); header = responseHeaders.get(1); assertThat(header.getName(), equalTo("X-Test")); assertThat(header.getValue(), equalTo("value")); + header = responseHeaders.get(2); + assertThat(header.getName(), equalTo("Set-Cookie")); + assertThat(header.getValue(), startsWith("cookieA=valueA;domain=domain;path=/path;expires=")); + assertThat(header.getValue(), endsWith(";secure;httpOnly")); + } + + // SPR-14169 + @Test + public void buildResponseHeadersNullDomainDefaulted() throws Exception { + Cookie cookie = new Cookie("cookieA", "valueA"); + this.response.addCookie(cookie); + WebResponse webResponse = this.responseBuilder.build(); + + List<NameValuePair> responseHeaders = webResponse.getResponseHeaders(); + assertThat(responseHeaders.size(), equalTo(1)); + NameValuePair header = responseHeaders.get(0); + assertThat(header.getName(), equalTo("Set-Cookie")); + assertThat(header.getValue(), equalTo("cookieA=valueA")); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java index 85e41b02..f60e1a76 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java @@ -19,6 +19,7 @@ package org.springframework.test.web.servlet.htmlunit.webdriver; import java.io.IOException; import javax.servlet.http.HttpServletRequest; +import com.gargoylesoftware.htmlunit.util.Cookie; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,12 +28,13 @@ import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; +import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; @@ -48,7 +50,7 @@ import static org.junit.Assert.*; * @author Sam Brannen * @since 4.2 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @WebAppConfiguration public class MockMvcHtmlUnitDriverBuilderTests { @@ -84,16 +86,16 @@ public class MockMvcHtmlUnitDriverBuilderTests { WebConnectionHtmlUnitDriver otherDriver = new WebConnectionHtmlUnitDriver(); this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).withDelegate(otherDriver).build(); - assertMvcProcessed("http://localhost/test"); - Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); + assertMockMvcUsed("http://localhost/test"); + Assume.group(TestGroup.PERFORMANCE, () -> assertMockMvcNotUsed("http://example.com/")); } @Test public void mockMvcSetupWithDefaultDriverDelegate() throws Exception { this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build(); - assertMvcProcessed("http://localhost/test"); - Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); + assertMockMvcUsed("http://localhost/test"); + Assume.group(TestGroup.PERFORMANCE, () -> assertMockMvcNotUsed("http://example.com/")); } @Test @@ -108,11 +110,25 @@ public class MockMvcHtmlUnitDriverBuilderTests { assertFalse(this.driver.isJavascriptEnabled()); } - private void assertMvcProcessed(String url) throws Exception { + @Test // SPR-14066 + public void cookieManagerShared() throws Exception { + WebConnectionHtmlUnitDriver otherDriver = new WebConnectionHtmlUnitDriver(); + this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build(); + this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc) + .withDelegate(otherDriver).build(); + + assertThat(get("http://localhost/"), equalTo("")); + Cookie cookie = new Cookie("localhost", "cookie", "cookieManagerShared"); + otherDriver.getWebClient().getCookieManager().addCookie(cookie); + assertThat(get("http://localhost/"), equalTo("cookieManagerShared")); + } + + + private void assertMockMvcUsed(String url) throws Exception { assertThat(get(url), containsString(EXPECTED_BODY)); } - private void assertDelegateProcessed(String url) throws Exception { + private void assertMockMvcNotUsed(String url) throws Exception { assertThat(get(url), not(containsString(EXPECTED_BODY))); } @@ -136,4 +152,13 @@ public class MockMvcHtmlUnitDriverBuilderTests { } } -}
\ No newline at end of file + @RestController + static class CookieController { + + @RequestMapping(path = "/", produces = "text/plain") + String cookie(@CookieValue("cookie") String cookie) { + return cookie; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java index 90ab35ba..53c76989 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.request; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.security.Principal; import java.util.Arrays; import java.util.Collections; @@ -25,7 +26,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; - import javax.servlet.ServletContext; import javax.servlet.http.Cookie; @@ -43,8 +43,12 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.support.SessionFlashMapManager; +import org.springframework.web.util.UriComponentsBuilder; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; /** * Unit tests for building a {@link MockHttpServletRequest} with @@ -270,6 +274,20 @@ public class MockHttpServletRequestBuilderTests { } @Test + public void requestParameterFromRequestBodyFormData() throws Exception { + String contentType = "application/x-www-form-urlencoded;charset=UTF-8"; + String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3"; + + MockHttpServletRequest request = new MockHttpServletRequestBuilder(HttpMethod.POST, "/foo") + .contentType(contentType).content(body.getBytes(Charset.forName("UTF-8"))) + .buildRequest(this.servletContext); + + assertArrayEquals(new String[] {"value 1"}, request.getParameterMap().get("name 1")); + assertArrayEquals(new String[] {"value A", "value B"}, request.getParameterMap().get("name 2")); + assertArrayEquals(new String[] {null}, request.getParameterMap().get("name 3")); + } + + @Test public void acceptHeader() { this.builder.accept(MediaType.TEXT_HTML, MediaType.APPLICATION_XML); @@ -429,7 +447,7 @@ public class MockHttpServletRequestBuilderTests { @Test public void sessionAttributes() { - Map<String, Object> map = new HashMap<String, Object>(); + Map<String, Object> map = new HashMap<>(); map.put("foo", "bar"); this.builder.sessionAttrs(map); @@ -472,6 +490,7 @@ public class MockHttpServletRequestBuilderTests { } // SPR-12945 + @Test public void mergeInvokesDefaultRequestPostProcessorFirst() { final String ATTR = "ATTR"; @@ -492,6 +511,20 @@ public class MockHttpServletRequestBuilderTests { assertEquals(EXEPCTED, request.getAttribute(ATTR)); } + // SPR-13719 + + @Test + public void arbitraryMethod() { + String httpMethod = "REPort"; + URI url = UriComponentsBuilder.fromPath("/foo/{bar}").buildAndExpand(42).toUri(); + this.builder = new MockHttpServletRequestBuilder(httpMethod, url); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + + assertEquals(httpMethod, request.getMethod()); + assertEquals("/foo/42", request.getPathInfo()); + } + private final class User implements Principal { diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java index bf0b5885..b587a34e 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -29,6 +29,7 @@ import org.springframework.test.web.servlet.StubMvcResult; * @author Rossen Stoyanchev * @author Craig Andrews * @author Sam Brannen + * @author Brian Clozel */ public class JsonPathResultMatchersTests { @@ -41,7 +42,7 @@ public class JsonPathResultMatchersTests { "'emptyString': '', " + // "'emptyArray': [], " + // "'emptyMap': {} " + // - "}"; + "}"; private static final StubMvcResult stubMvcResult; @@ -57,7 +58,6 @@ public class JsonPathResultMatchersTests { } } - @Test public void value() throws Exception { new JsonPathResultMatchers("$.str").value("foo").match(stubMvcResult); @@ -233,4 +233,42 @@ public class JsonPathResultMatchersTests { new JsonPathResultMatchers("$.arr").isString().match(stubMvcResult); } + @Test(expected = AssertionError.class) + public void valueWithJsonPrefixNotConfigured() throws Exception { + String jsonPrefix = "prefix"; + StubMvcResult result = createPrefixedStubMvcResult(jsonPrefix); + new JsonPathResultMatchers("$.str").value("foo").match(result); + } + + @Test(expected = AssertionError.class) + public void valueWithJsonWrongPrefix() throws Exception { + String jsonPrefix = "prefix"; + StubMvcResult result = createPrefixedStubMvcResult(jsonPrefix); + new JsonPathResultMatchers("$.str").prefix("wrong").value("foo").match(result); + } + + @Test + public void valueWithJsonPrefix() throws Exception { + String jsonPrefix = "prefix"; + StubMvcResult result = createPrefixedStubMvcResult(jsonPrefix); + new JsonPathResultMatchers("$.str").prefix(jsonPrefix).value("foo").match(result); + } + + @Test(expected = AssertionError.class) + public void prefixWithPayloadNotLongEnough() throws Exception { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.addHeader("Content-Type", "application/json"); + response.getWriter().print(new String("test".getBytes("ISO-8859-1"))); + StubMvcResult result = new StubMvcResult(null, null, null, null, null, null, response); + + new JsonPathResultMatchers("$.str").prefix("prefix").value("foo").match(result); + } + + private StubMvcResult createPrefixedStubMvcResult(String jsonPrefix) throws Exception { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.addHeader("Content-Type", "application/json"); + response.getWriter().print(jsonPrefix + new String(RESPONSE_CONTENT.getBytes("ISO-8859-1"))); + return new StubMvcResult(null, null, null, null, null, null, response); + } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/StatusResultMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/StatusResultMatchersTests.java index 7b1c04d4..ead30b9e 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/result/StatusResultMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/StatusResultMatchersTests.java @@ -59,7 +59,7 @@ public class StatusResultMatchersTests { List<AssertionError> failures = new ArrayList<AssertionError>(); - for(HttpStatus status : HttpStatus.values()) { + for (HttpStatus status : HttpStatus.values()) { MockHttpServletResponse response = new MockHttpServletResponse(); response.setStatus(status.value()); MvcResult mvcResult = new StubMvcResult(request, null, null, null, null, null, response); @@ -91,9 +91,7 @@ public class StatusResultMatchersTests { @Test public void statusRanges() throws Exception { - - for(HttpStatus status : HttpStatus.values()) { - + for (HttpStatus status : HttpStatus.values()) { MockHttpServletResponse response = new MockHttpServletResponse(); response.setStatus(status.value()); MvcResult mvcResult = new StubMvcResult(request, null, null, null, null, null, response); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/AsyncControllerJavaConfigTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/AsyncControllerJavaConfigTests.java index 31943512..0613048d 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/AsyncControllerJavaConfigTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/AsyncControllerJavaConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -23,6 +23,7 @@ import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; + import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +37,7 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.request.async.CallableProcessingInterceptor; @@ -55,6 +56,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * Tests with Java configuration. * * @author Rossen Stoyanchev + * @author Sam Brannen */ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @@ -123,7 +125,7 @@ public class AsyncControllerJavaConfigTests { @RestController static class AsyncController { - @RequestMapping(path = "/callable") + @GetMapping("/callable") public Callable<Map<String, String>> getCallable() { return () -> Collections.singletonMap("key", "value"); } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java index 5e115f66..ee365936 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -16,25 +16,24 @@ package org.springframework.test.web.servlet.samples.context; -import org.springframework.stereotype.Controller; import org.springframework.test.web.Person; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; -@Controller +@RestController +@RequestMapping("/person") public class PersonController { private final PersonDao personDao; - public PersonController(PersonDao personDao) { + PersonController(PersonDao personDao) { this.personDao = personDao; } - @RequestMapping(value="/person/{id}", method=RequestMethod.GET) - @ResponseBody + @GetMapping("/{id}") public Person getPerson(@PathVariable long id) { return this.personDao.getPerson(id); } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java index 48038763..c922297f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/AsyncTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -17,6 +17,7 @@ package org.springframework.test.web.servlet.samples.standalone; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; @@ -26,6 +27,7 @@ import org.junit.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.test.web.Person; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -36,6 +38,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; +import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import static org.junit.Assert.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -67,11 +70,39 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); } @Test + public void streaming() throws Exception { + this.mockMvc.perform(get("/1").param("streaming", "true")) + .andExpect(request().asyncStarted()) + .andDo(r -> r.getAsyncResult()) // fetch async result similar to "asyncDispatch" builder + .andExpect(status().isOk()) + .andExpect(content().string("name=Joe")); + } + + @Test + public void streamingSlow() throws Exception { + this.mockMvc.perform(get("/1").param("streamingSlow", "true")) + .andExpect(request().asyncStarted()) + .andDo(r -> r.getAsyncResult()) + .andExpect(status().isOk()) + .andExpect(content().string("name=Joe&someBoolean=true")); + } + + @Test + public void streamingJson() throws Exception { + this.mockMvc.perform(get("/1").param("streamingJson", "true")) + .andExpect(request().asyncStarted()) + .andDo(r -> r.getAsyncResult()) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.5}")); + } + + @Test public void deferredResult() throws Exception { MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true")) .andExpect(request().asyncStarted()) @@ -81,7 +112,7 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); } @@ -94,7 +125,7 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); } @@ -122,7 +153,7 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); } @@ -137,7 +168,7 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); } @@ -161,7 +192,7 @@ public class AsyncTests { this.mockMvc.perform(asyncDispatch(mvcResult)) .andDo(print(writer)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); assertTrue(writer.toString().contains("Async started = false")); @@ -184,6 +215,31 @@ public class AsyncTests { return () -> new Person("Joe"); } + @RequestMapping(params = "streaming") + public StreamingResponseBody getStreaming() { + return os -> os.write("name=Joe".getBytes()); + } + + @RequestMapping(params = "streamingSlow") + public StreamingResponseBody getStreamingSlow() { + return os -> { + os.write("name=Joe".getBytes()); + try { + Thread.sleep(200); + os.write("&someBoolean=true".getBytes()); + } + catch (InterruptedException e) { + /* no-op */ + } + }; + } + + @RequestMapping(params = "streamingJson") + public ResponseEntity<StreamingResponseBody> getStreamingJson() { + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON_UTF8) + .body(os -> os.write("{\"name\":\"Joe\",\"someDouble\":0.5}".getBytes(StandardCharsets.UTF_8))); + } + @RequestMapping(params = "deferredResult") public DeferredResult<Person> getDeferredResult() { DeferredResult<Person> deferredResult = new DeferredResult<Person>(); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ViewResolutionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ViewResolutionTests.java index 0ac2b07c..b286f626 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ViewResolutionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ViewResolutionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -53,10 +53,7 @@ public class ViewResolutionTests { @Test public void testJspOnly() throws Exception { - - InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); - viewResolver.setPrefix("/WEB-INF/"); - viewResolver.setSuffix(".jsp"); + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver("/WEB-INF/", ".jsp"); standaloneSetup(new PersonController()).setViewResolvers(viewResolver).build() .perform(get("/person/Corea")) @@ -68,7 +65,6 @@ public class ViewResolutionTests { @Test public void testJsonOnly() throws Exception { - standaloneSetup(new PersonController()).setSingleView(new MappingJackson2JsonView()).build() .perform(get("/person/Corea")) .andExpect(status().isOk()) @@ -78,7 +74,6 @@ public class ViewResolutionTests { @Test public void testXmlOnly() throws Exception { - Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(Person.class); @@ -91,7 +86,6 @@ public class ViewResolutionTests { @Test public void testContentNegotiation() throws Exception { - Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(Person.class); @@ -131,7 +125,6 @@ public class ViewResolutionTests { @Test public void defaultViewResolver() throws Exception { - standaloneSetup(new PersonController()).build() .perform(get("/person/Corea")) .andExpect(model().attribute("person", hasProperty("name", equalTo("Corea")))) diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java index 0c470ea5..d0d60138 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java @@ -16,8 +16,6 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; -import java.nio.charset.Charset; - import org.junit.Before; import org.junit.Test; @@ -44,8 +42,6 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; */ public class ContentAssertionTests { - public static final MediaType TEXT_PLAIN_UTF8 = new MediaType("text", "plain", Charset.forName("UTF-8")); - private MockMvc mockMvc; @Before @@ -56,8 +52,10 @@ public class ContentAssertionTests { @Test public void testContentType() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) - .andExpect(content().contentType(MediaType.TEXT_PLAIN)) - .andExpect(content().contentType("text/plain")); + .andExpect(content().contentType(MediaType.valueOf("text/plain;charset=ISO-8859-1"))) + .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) + .andExpect(content().contentTypeCompatibleWith("text/plain")) + .andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN)); this.mockMvc.perform(get("/handleUtf8")) .andExpect(content().contentType(MediaType.valueOf("text/plain;charset=UTF-8"))) diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java index 9d3b883d..2c671bbf 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -18,66 +18,84 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; import java.lang.reflect.Method; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; -import org.springframework.stereotype.Controller; +import org.springframework.http.ResponseEntity; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.bind.annotation.RequestMapping; - -import static org.hamcrest.Matchers.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.handler; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; +import static org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.on; /** - * Examples of expectations on the handler or handler method that executed the request. - * - * <p>Note that in most cases "handler" is synonymous with "controller". - * For example an {@code @Controller} is a kind of handler. + * Examples of expectations on the controller type and controller method. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public class HandlerAssertionTests { - private MockMvc mockMvc; + private final MockMvc mockMvc = standaloneSetup(new SimpleController()).alwaysExpect(status().isOk()).build(); + + @Rule + public final ExpectedException exception = ExpectedException.none(); - @Before - public void setup() { - this.mockMvc = standaloneSetup(new SimpleController()).alwaysExpect(status().isOk()).build(); - } @Test - public void testHandlerType() throws Exception { + public void handlerType() throws Exception { this.mockMvc.perform(get("/")).andExpect(handler().handlerType(SimpleController.class)); } @Test - public void testHandlerMethodNameEqualTo() throws Exception { - this.mockMvc.perform(get("/")).andExpect(handler().methodName("handle")); + public void methodCallOnNonMock() throws Exception { + exception.expect(AssertionError.class); + exception.expectMessage("The supplied object [bogus] is not an instance of"); + exception.expectMessage(MvcUriComponentsBuilder.MethodInvocationInfo.class.getName()); + exception.expectMessage("Ensure that you invoke the handler method via MvcUriComponentsBuilder.on()"); - // Hamcrest matcher.. - this.mockMvc.perform(get("/")).andExpect(handler().methodName(equalTo("handle"))); + this.mockMvc.perform(get("/")).andExpect(handler().methodCall("bogus")); } @Test - public void testHandlerMethodNameMatcher() throws Exception { + public void methodCall() throws Exception { + this.mockMvc.perform(get("/")).andExpect(handler().methodCall(on(SimpleController.class).handle())); + } + + @Test + public void methodName() throws Exception { + this.mockMvc.perform(get("/")).andExpect(handler().methodName("handle")); + } + + @Test + public void methodNameMatchers() throws Exception { + this.mockMvc.perform(get("/")).andExpect(handler().methodName(equalTo("handle"))); this.mockMvc.perform(get("/")).andExpect(handler().methodName(is(not("save")))); } @Test - public void testHandlerMethod() throws Exception { + public void method() throws Exception { Method method = SimpleController.class.getMethod("handle"); this.mockMvc.perform(get("/")).andExpect(handler().method(method)); } - @Controller - private static class SimpleController { + @RestController + static class SimpleController { @RequestMapping("/") - public String handle() { - return "view"; + public ResponseEntity<Void> handle() { + return ResponseEntity.ok().build(); } } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java index e81824c8..38fbba01 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -16,6 +16,11 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + import org.junit.Before; import org.junit.Test; @@ -28,16 +33,22 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.WebRequest; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.springframework.http.HttpHeaders.IF_MODIFIED_SINCE; +import static org.springframework.http.HttpHeaders.LAST_MODIFIED; +import static org.springframework.http.HttpHeaders.VARY; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; /** * Examples of expectations on response header values. @@ -48,86 +59,95 @@ import java.util.TimeZone; */ public class HeaderAssertionTests { - private static final String EXPECTED_ASSERTION_ERROR_MSG = "Should have thrown an AssertionError"; - - private static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + private static final String ERROR_MESSAGE = "Should have thrown an AssertionError"; - private static final String LAST_MODIFIED = "Last-Modified"; - - private final long currentTime = System.currentTimeMillis(); private String now; - private String oneMinuteAgo; + private String minuteAgo; - private String oneSecondLater; + private String secondLater; private MockMvc mockMvc; - private PersonController personController; + private final long currentTime = System.currentTimeMillis(); @Before public void setup() { SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - this.now = dateFormat.format(new Date(currentTime)); - this.oneMinuteAgo = dateFormat.format(new Date(currentTime - (1000 * 60))); - this.oneSecondLater = dateFormat.format(new Date(currentTime + 1000)); - this.personController = new PersonController(); - this.personController.setStubTimestamp(currentTime); - this.mockMvc = standaloneSetup(this.personController).build(); + this.now = dateFormat.format(new Date(this.currentTime)); + this.minuteAgo = dateFormat.format(new Date(this.currentTime - (1000 * 60))); + this.secondLater = dateFormat.format(new Date(this.currentTime + 1000)); + + PersonController controller = new PersonController(); + controller.setStubTimestamp(this.currentTime); + this.mockMvc = standaloneSetup(controller).build(); } + @Test public void stringWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().string(LAST_MODIFIED, now)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().string(LAST_MODIFIED, now)); } @Test public void stringWithMatcherAndCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().string(LAST_MODIFIED, equalTo(now))); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().string(LAST_MODIFIED, equalTo(now))); + } + + @Test + public void multiStringHeaderValue() throws Exception { + this.mockMvc.perform(get("/persons/1")).andExpect(header().stringValues(VARY, "foo", "bar")); + } + + @SuppressWarnings("unchecked") + @Test + public void multiStringHeaderValueWithMatchers() throws Exception { + this.mockMvc.perform(get("/persons/1")) + .andExpect(header().stringValues(VARY, hasItems(containsString("foo"), startsWith("bar")))); } @Test public void dateValueWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().dateValue(LAST_MODIFIED, currentTime)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().dateValue(LAST_MODIFIED, this.currentTime)); } @Test public void longValueWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1"))// - .andExpect(header().longValue("X-Rate-Limiting", 42)); + this.mockMvc.perform(get("/persons/1")) + .andExpect(header().longValue("X-Rate-Limiting", 42)); } @Test public void stringWithMissingResponseHeader() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().string("X-Custom-Header", (String) null)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().stringValues("X-Custom-Header")); } @Test public void stringWithMatcherAndMissingResponseHeader() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().string("X-Custom-Header", nullValue())); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().string("X-Custom-Header", nullValue())); } @Test public void longValueWithMissingResponseHeader() throws Exception { try { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().longValue("X-Custom-Header", 99L)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().longValue("X-Custom-Header", 99L)); - fail(EXPECTED_ASSERTION_ERROR_MSG); + fail(ERROR_MESSAGE); } catch (AssertionError e) { - if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) { + if (ERROR_MESSAGE.equals(e.getMessage())) { throw e; } assertEquals("Response does not contain header " + "X-Custom-Header", e.getMessage()); @@ -138,32 +158,30 @@ public class HeaderAssertionTests { @Test public void doesNotExist() throws Exception { - this.mockMvc.perform(get("/persons/1")) - .andExpect(header().doesNotExist("X-Custom-Header")); + this.mockMvc.perform(get("/persons/1")).andExpect(header().doesNotExist("X-Custom-Header")); } // SPR-10771 @Test(expected = AssertionError.class) public void doesNotExistFail() throws Exception { - this.mockMvc.perform(get("/persons/1")) - .andExpect(header().doesNotExist(LAST_MODIFIED)); + this.mockMvc.perform(get("/persons/1")).andExpect(header().doesNotExist(LAST_MODIFIED)); } @Test public void stringWithIncorrectResponseHeaderValue() throws Exception { - assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, oneSecondLater), oneSecondLater); + assertIncorrectResponseHeader(header().string(LAST_MODIFIED, secondLater), secondLater); } @Test public void stringWithMatcherAndIncorrectResponseHeaderValue() throws Exception { - assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, equalTo(oneSecondLater)), oneSecondLater); + assertIncorrectResponseHeader(header().string(LAST_MODIFIED, equalTo(secondLater)), secondLater); } @Test public void dateValueWithIncorrectResponseHeaderValue() throws Exception { - long unexpected = currentTime + 1000; - assertIncorrectResponseHeaderValue(header().dateValue(LAST_MODIFIED, unexpected), oneSecondLater); + long unexpected = this.currentTime + 1000; + assertIncorrectResponseHeader(header().dateValue(LAST_MODIFIED, unexpected), secondLater); } @Test(expected = AssertionError.class) @@ -171,21 +189,20 @@ public class HeaderAssertionTests { this.mockMvc.perform(get("/persons/1")).andExpect(header().longValue("X-Rate-Limiting", 1)); } - private void assertIncorrectResponseHeaderValue(ResultMatcher resultMatcher, String unexpected) throws Exception { + private void assertIncorrectResponseHeader(ResultMatcher matcher, String unexpected) throws Exception { try { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(resultMatcher); + this.mockMvc.perform(get("/persons/1") + .header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(matcher); - fail(EXPECTED_ASSERTION_ERROR_MSG); + fail(ERROR_MESSAGE); } catch (AssertionError e) { - if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) { + if (ERROR_MESSAGE.equals(e.getMessage())) { throw e; } - // [SPR-10659] Ensure that the header name is included in the message - // - // We don't use assertEquals() since we cannot control the formatting - // produced by JUnit or Hamcrest. + // SPR-10659: ensure header name is in the message + // Unfortunately, we can't control formatting from JUnit or Hamcrest. assertMessageContains(e, "Response header " + LAST_MODIFIED); assertMessageContains(e, unexpected); assertMessageContains(e, now); @@ -198,8 +215,6 @@ public class HeaderAssertionTests { } - // ------------------------------------------------------------------------- - @Controller private static class PersonController { @@ -216,6 +231,7 @@ public class HeaderAssertionTests { .ok() .lastModified(calculateLastModified(id)) .header("X-Rate-Limiting", "42") + .header("Vary", "foo", "bar") .body(new Person("Jason")); } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/XpathAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/XpathAssertionTests.java index 4ae88e7a..c1e25791 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/XpathAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/XpathAssertionTests.java @@ -158,7 +158,7 @@ public class XpathAssertionTests { standaloneSetup(new BlogFeedController()).build() .perform(get("/blog.atom").accept(MediaType.APPLICATION_ATOM_XML)) .andExpect(status().isOk()) - .andExpect(content().contentType(MediaType.APPLICATION_ATOM_XML)) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_ATOM_XML)) .andExpect(xpath("//feed/title").string("Test Feed")) .andExpect(xpath("//feed/icon").string("http://www.example.com/favicon.ico")); } |