Browse Source
Prior to this commit, ClassLevelDirtiesContextTests existed for verifying the expected behavior of @DirtiesContext declared at the class level in conjunction with JUnit and SpringJUnit4ClassRunner. This commit introduces analogous tests for TestNG in the new ClassLevelDirtiesContextTestNGTests class. Furthermore, ContextCacheTestUtils and TrackingTestNGTestListener have been introduced to reduce code duplication across the test suite. Issue: SPR-12918pull/780/head
Sam Brannen
10 years ago
7 changed files with 436 additions and 134 deletions
@ -0,0 +1,262 @@
@@ -0,0 +1,262 @@
|
||||
/* |
||||
* 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. |
||||
* 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; |
||||
|
||||
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.annotation.DirtiesContext; |
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode; |
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; |
||||
import org.springframework.test.context.support.DirtiesContextTestExecutionListener; |
||||
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; |
||||
import org.springframework.test.context.testng.TrackingTestNGTestListener; |
||||
|
||||
import org.testng.TestNG; |
||||
|
||||
import static org.junit.Assert.*; |
||||
import static org.springframework.test.context.ContextCacheTestUtils.*; |
||||
|
||||
/** |
||||
* JUnit 4 based integration test which verifies correct {@linkplain ContextCache |
||||
* application context caching} in conjunction with Spring's TestNG support |
||||
* and {@link DirtiesContext @DirtiesContext} at the class level. |
||||
* |
||||
* <p>This class is a direct copy of {@link ClassLevelDirtiesContextTests}, |
||||
* modified to verify behavior in conjunction with TestNG. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.2 |
||||
*/ |
||||
@RunWith(JUnit4.class) |
||||
public class ClassLevelDirtiesContextTestNGTests { |
||||
|
||||
private static final AtomicInteger cacheHits = new AtomicInteger(0); |
||||
private static final AtomicInteger cacheMisses = new AtomicInteger(0); |
||||
|
||||
|
||||
private static final void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) { |
||||
final int expectedTestFailureCount = 0; |
||||
final int expectedTestStartedCount = expectedTestCount; |
||||
final int expectedTestFinishedCount = expectedTestCount; |
||||
|
||||
final TrackingTestNGTestListener listener = new TrackingTestNGTestListener(); |
||||
final TestNG testNG = new TestNG(); |
||||
testNG.addListener(listener); |
||||
testNG.setTestClasses(new Class<?>[] { testClass }); |
||||
testNG.setVerbose(0); |
||||
testNG.run(); |
||||
|
||||
assertEquals("Failures for test class [" + testClass + "].", expectedTestFailureCount, |
||||
listener.testFailureCount); |
||||
assertEquals("Tests started for test class [" + testClass + "].", expectedTestStartedCount, |
||||
listener.testStartCount); |
||||
assertEquals("Successful tests for test class [" + testClass + "].", expectedTestFinishedCount, |
||||
listener.testSuccessCount); |
||||
} |
||||
|
||||
@BeforeClass |
||||
public static void verifyInitialCacheState() { |
||||
ContextCache contextCache = TestContextManager.contextCache; |
||||
contextCache.clear(); |
||||
contextCache.clearStatistics(); |
||||
cacheHits.set(0); |
||||
cacheMisses.set(0); |
||||
assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get()); |
||||
} |
||||
|
||||
@Test |
||||
public void verifyDirtiesContextBehavior() throws Exception { |
||||
|
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode", |
||||
0, cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1); |
||||
assertContextCacheStatistics( |
||||
"after inherited class-level @DirtiesContext with clean test method and default class mode", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode", |
||||
0, cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1); |
||||
assertContextCacheStatistics( |
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_CLASS mode", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3); |
||||
assertContextCacheStatistics( |
||||
"after class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2)); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3); |
||||
assertContextCacheStatistics( |
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2)); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(), |
||||
cacheMisses.incrementAndGet()); |
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(), |
||||
cacheMisses.incrementAndGet()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0, |
||||
cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0, |
||||
cacheHits.get(), cacheMisses.incrementAndGet()); |
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1); |
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0, |
||||
cacheHits.get(), cacheMisses.incrementAndGet()); |
||||
assertBehaviorForCleanTestCase(); |
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1); |
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode", |
||||
0, cacheHits.incrementAndGet(), cacheMisses.get()); |
||||
} |
||||
|
||||
private void assertBehaviorForCleanTestCase() { |
||||
runTestClassAndAssertStats(CleanTestCase.class, 1); |
||||
assertContextCacheStatistics("after clean test class", 1, cacheHits.get(), cacheMisses.incrementAndGet()); |
||||
} |
||||
|
||||
@AfterClass |
||||
public static void verifyFinalCacheState() { |
||||
assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get()); |
||||
} |
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, |
||||
DirtiesContextTestExecutionListener.class }, inheritListeners = false) |
||||
@ContextConfiguration |
||||
public static abstract class BaseTestCase extends AbstractTestNGSpringContextTests { |
||||
|
||||
@Configuration |
||||
static class Config { |
||||
/* no beans */ |
||||
} |
||||
|
||||
|
||||
@Autowired |
||||
protected ApplicationContext applicationContext; |
||||
|
||||
|
||||
protected void assertApplicationContextWasAutowired() { |
||||
org.testng.Assert.assertNotNull(this.applicationContext, |
||||
"The application context should have been autowired."); |
||||
} |
||||
} |
||||
|
||||
public static final class CleanTestCase extends BaseTestCase { |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
|
||||
} |
||||
|
||||
@DirtiesContext |
||||
public static class ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends BaseTestCase { |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
} |
||||
|
||||
public static class InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase extends |
||||
ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase { |
||||
} |
||||
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_CLASS) |
||||
public static class ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends BaseTestCase { |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
} |
||||
|
||||
public static class InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase extends |
||||
ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase { |
||||
} |
||||
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) |
||||
public static class ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends BaseTestCase { |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired1() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired2() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
|
||||
@org.testng.annotations.Test |
||||
public void verifyContextWasAutowired3() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
} |
||||
|
||||
public static class InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase extends |
||||
ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase { |
||||
} |
||||
|
||||
@DirtiesContext |
||||
public static class ClassLevelDirtiesContextWithDirtyMethodsTestCase extends BaseTestCase { |
||||
|
||||
@org.testng.annotations.Test |
||||
@DirtiesContext |
||||
public void dirtyContext() { |
||||
assertApplicationContextWasAutowired(); |
||||
} |
||||
} |
||||
|
||||
public static class InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase extends |
||||
ClassLevelDirtiesContextWithDirtyMethodsTestCase { |
||||
} |
||||
|
||||
} |
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
/* |
||||
* 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. |
||||
* 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; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
/** |
||||
* Collection of utility methods for testing scenarios involving the |
||||
* {@link ContextCache}. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.2 |
||||
*/ |
||||
public class ContextCacheTestUtils { |
||||
|
||||
/** |
||||
* Assert the statistics of the context cache in {@link TestContextManager}. |
||||
* |
||||
* @param usageScenario the scenario in which the statistics are used |
||||
* @param expectedSize the expected number of contexts in the cache |
||||
* @param expectedHitCount the expected hit count |
||||
* @param expectedMissCount the expected miss count |
||||
*/ |
||||
public static final void assertContextCacheStatistics(String usageScenario, int expectedSize, int expectedHitCount, |
||||
int expectedMissCount) { |
||||
assertContextCacheStatistics(TestContextManager.contextCache, usageScenario, expectedSize, expectedHitCount, |
||||
expectedMissCount); |
||||
} |
||||
|
||||
/** |
||||
* Assert the statistics of the supplied context cache. |
||||
* |
||||
* @param contextCache the cache to assert against |
||||
* @param usageScenario the scenario in which the statistics are used |
||||
* @param expectedSize the expected number of contexts in the cache |
||||
* @param expectedHitCount the expected hit count |
||||
* @param expectedMissCount the expected miss count |
||||
*/ |
||||
public static final void assertContextCacheStatistics(ContextCache contextCache, String usageScenario, |
||||
int expectedSize, int expectedHitCount, int expectedMissCount) { |
||||
|
||||
assertEquals("Verifying number of contexts in cache (" + usageScenario + ").", expectedSize, |
||||
contextCache.size()); |
||||
assertEquals("Verifying number of cache hits (" + usageScenario + ").", expectedHitCount, |
||||
contextCache.getHitCount()); |
||||
assertEquals("Verifying number of cache misses (" + usageScenario + ").", expectedMissCount, |
||||
contextCache.getMissCount()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
/* |
||||
* 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. |
||||
* 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.testng; |
||||
|
||||
import org.testng.ITestContext; |
||||
import org.testng.ITestListener; |
||||
import org.testng.ITestResult; |
||||
|
||||
/** |
||||
* Simple {@link ITestListener} which tracks how many times certain TestNG |
||||
* callback methods were called: only intended for the integration test suite. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.2 |
||||
*/ |
||||
public class TrackingTestNGTestListener implements ITestListener { |
||||
|
||||
public int testStartCount = 0; |
||||
public int testSuccessCount = 0; |
||||
public int testFailureCount = 0; |
||||
public int failedConfigurationsCount = 0; |
||||
|
||||
|
||||
@Override |
||||
public void onFinish(ITestContext testContext) { |
||||
this.failedConfigurationsCount += testContext.getFailedConfigurations().size(); |
||||
} |
||||
|
||||
@Override |
||||
public void onStart(ITestContext testContext) { |
||||
} |
||||
|
||||
@Override |
||||
public void onTestFailedButWithinSuccessPercentage(ITestResult testResult) { |
||||
} |
||||
|
||||
@Override |
||||
public void onTestFailure(ITestResult testResult) { |
||||
this.testFailureCount++; |
||||
} |
||||
|
||||
@Override |
||||
public void onTestSkipped(ITestResult testResult) { |
||||
} |
||||
|
||||
@Override |
||||
public void onTestStart(ITestResult testResult) { |
||||
this.testStartCount++; |
||||
} |
||||
|
||||
@Override |
||||
public void onTestSuccess(ITestResult testResult) { |
||||
this.testSuccessCount++; |
||||
} |
||||
} |
Loading…
Reference in new issue