Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

SPR-10217 Implement JUnit 4 Support using Rules #222

Closed
wants to merge 1 commit into from

4 participants

@marschall

Currently JUnit 4 support is provided by SpringJUnit4ClassRunner which
is a custom BlockJUnit4ClassRunner. There is no support for using other
runners like Theories or Parameterized or 3rd party runners like
MockitoJUnitRunner. A runner based approach does not seem to offer much
promise as runners are not composable, a custom Spring version of every
runner has to be developed and maintained.

With JUnit 4.9+ the preferred way to implement such behavior is to use
rules. Unlike runners there can be several ones of them and they can be
composed. In theory TestExecutionListener could be deprecated and be
replaced with standard JUnit rules but this seems to be a bit on the
drastic side.

This proposed implementation is using both a class rule and a method
rule. The class rule creates the TestContextManager, runs all the class
level callbacks and class level checks. The method rule runs all the
instance level callbacks and method level checks. I did not see a way
to implement the current functionality offered by
SpringJUnit4ClassRunner using only one rule.
Using two rules has the advantage that the implementation is cleaner
because it better separates the concerns. However it has the
disadvantage that it's harder to set up because both a method rule and
a class rule are needed. This also increases the potential for
misconfiguration.

The method rule has to be a MethodRule instead of a TestRule because
only the former has access to the test object with we need to perform
injection. This interface used to be deprecated once but doesn't seem
to be anymore. This creates a certain risk that it will be deprectated
again and potentially be remvoed in the future. An additional drawback
is that MethodRule unlike TestRule can only be defined in fields and
not methods. This is an unfortunate consequence of the implementation
of org.junit.runners.model.TestClass. As JUnit does not do
Field#setAccessible(true) this means that tests will have to be defined
in public fields.

Another minor issue is that tests not run because of IfProfileValue
will still show up in the Eclipse test tree, just blank.

In conclusion while the given implementation has some downsides I don't
see any other possible implementations given the current state of
affairs in JUnit.

  • Add SpringJUnitClassRule for all the class level processing
  • Add SpringJUnitMethodRule for all the method level processing
  • Add tests for the rules

SPR-10217

@sbrannen sbrannen was assigned
@sbrannen
Owner

See SPR-7731 instead of SPR-10217.

@eeichinger

just a quick note that the profile check could make use of assumptions: from the org.junit.Assume javadoc "The default JUnit runner treats tests with failing assumptions as ignored"

assumeTrue("required profile not active", ProfileValueUtils.isTestEnabledInThisEnvironment(getTestClass().getJavaClass()));

should do the trick

@eeichinger

also it seems safe to stick with MethodRule - @Deprecated has been removed as of junit 4.11 due to numerous user requests and the junit team has no intention to deprecate it again: https://github.com/KentBeck/junit/pull/519

@marschall

In theory we could have single rule that implements both TestRule and MethodRule but it would still have to be defined twice since @Rule fields and methods must not be static.

public class SampleTests {

    @ClassRule
    public static final SpringJUnitRule CLASS_RULE = new SpringJUnitRule();

    @Rule
    public MethodRule methodRule = CLASS_RULE;

} 
@marschall

@eeichinger good idea I updated the pull request

@marschall marschall SPR-10217 Implement JUnit 4 Support using Rules
Currently JUnit 4 support is provided by SpringJUnit4ClassRunner which
is a custom BlockJUnit4ClassRunner. There is no support for using other
runners like Theories or Parameterized or 3rd party runners like
MockitoJUnitRunner. A runner based approach does not seem to offer much
promise as runners are not composable, a custom Spring version of every
runner has to be developed and maintained.

With JUnit 4.9+ the preferred way to implement such behavior is to use
rules. Unlike runners there can be several ones of them and they can be
composed. In theory TestExecutionListener could be deprecated and be
replaced with standard JUnit rules but this seems to be a bit on the
drastic side.

This proposed implementation is using both a class rule and a method
rule. The class rule creates the TestContextManager, runs all the class
level callbacks and class level checks. The method rule runs all the
instance level callbacks and method level checks. I did not see a way
to implement the current functionality offered by
SpringJUnit4ClassRunner using only one rule.
Using two rules has the advantage that the implementation is cleaner
because it better separates the concerns. However it has the
disadvantage that it's harder to set up because both a method rule and
a class rule are needed. This also increases the potential for
misconfiguration.

The method rule has to be a MethodRule instead of a TestRule because
only the former has access to the test object with we need to perform
injection. This interface used to be deprecated once but doesn't seem
to be anymore. This creates a certain risk that it will be deprectated
again and potentially be remvoed in the future. An additional drawback
is that MethodRule unlike TestRule can only be defined in fields and
not methods. This is an unfortunate consequence of the implementation
of org.junit.runners.model.TestClass. As JUnit does not do
Field#setAccessible(true) this means that tests will have to be defined
in public fields.

Another minor issue is that tests not run because of IfProfileValue
will still show up in the Eclipse test tree, just blank.

In conclusion while the given implementation has some downsides I don't
see any other possible implementations given the current state of
affairs in JUnit.

- Add SpringJUnitClassRule for all the class level processing
- Add SpringJUnitMethodRule for all the method level processing
- Add tests for the rules

SPR-10217
d830cdc
@eeichinger

@marschall cool. not sure how many people are actually using @BeforeClass, but I mostly don't. so it's a bit of an inconvenience always having to the define both rules. Asfaik you can safely create two separate instances of TestContextManager as they're accessing the same static contextcache anyway. This way one has to define the @ClassRule only if you really need it for @BeforeClass

Other than that I've taken your code and use it 2 projects already, works like a charme!

@marschall

@eeichinger also TestExecutionListener#beforeTestClass and TestExecutionListener#afterTestClass wouldn't fire. Although TestExecutionListener is redundant when you have rules available. I can see your point it makes it easier to use OTOH it's harder to debug why something doesn't doesn't work. It's a trade off, I can live with either solution.

And thanks for testing.

Edit:
Also more TestExecutionListener instances would be created.

@eeichinger

the TestExecutionListeners should be stateless anyway, so no problem. But I see your point that TestExecutionListeners might expect before/afterTestClass to be called before before/afterTest get called. None of the default TestExecutionListeners do so, but custom ones might break. Which I'd say leaves it up to the user to configure the @ClassRule if his test setups require so

just wondering: does the junit api allow for a classrule to register an instance rule?

@marschall

No, unfortunately a classrule (actually just a TestRule) just gets a callback to affect the class execution (before and after). Basically it's a higher order function.

There is a proposal for an API that would do exactly what we need but there doesn't seem to be any progress happening.

@eeichinger

send a pull request... :)

@dsaff dsaff referenced this pull request in junit-team/junit
Open

Add support for test pre-processors #766

@erizzo

The comments in SpringJUnitMethodRule mention that ExpectedException is not supported; is that indeed true? If so, can you elaborate a bit?

@sbrannen
Owner

The Javadoc for SpringJUnitMethodRule with regard to ExpectedException is admittedly misleading at a glance.

If you take a look at the imports in SpringJUnitMethodRule, you will notice that the class referenced in the Javadoc is org.springframework.test.annotation.ExpectedException (i.e., the @ExpectedException annotation that was supported in earlier versions of the Spring TestContext Framework).

So fear not: JUnit's org.junit.rules.ExpectedException (i.e., the ExpectedException Rule) should be fully supported when used in conjunction with SpringJUnitMethodRule.

@sbrannen
Owner

For what it's worth, @ExpectedException was permanently removed from the spring-test module in Spring Framework 4.0 (see SPR-10499). Thus, for modern versions of Spring there should no longer be any confusion. ;)

@sbrannen
Owner

@marschall and @eeichinger, thanks so much for all of your ideas and collaboration on this!

I've just committed support for this in Spring Framework 4.2 RC1 here: d1b1c4f.

Cheers,

Sam

@sbrannen sbrannen closed this
@sbrannen
Owner

Though... perhaps I should attribute the Assume idea in ProfileValueChecker to @eeichinger instead of @marschall. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 2, 2013
  1. @marschall

    SPR-10217 Implement JUnit 4 Support using Rules

    marschall authored
    Currently JUnit 4 support is provided by SpringJUnit4ClassRunner which
    is a custom BlockJUnit4ClassRunner. There is no support for using other
    runners like Theories or Parameterized or 3rd party runners like
    MockitoJUnitRunner. A runner based approach does not seem to offer much
    promise as runners are not composable, a custom Spring version of every
    runner has to be developed and maintained.
    
    With JUnit 4.9+ the preferred way to implement such behavior is to use
    rules. Unlike runners there can be several ones of them and they can be
    composed. In theory TestExecutionListener could be deprecated and be
    replaced with standard JUnit rules but this seems to be a bit on the
    drastic side.
    
    This proposed implementation is using both a class rule and a method
    rule. The class rule creates the TestContextManager, runs all the class
    level callbacks and class level checks. The method rule runs all the
    instance level callbacks and method level checks. I did not see a way
    to implement the current functionality offered by
    SpringJUnit4ClassRunner using only one rule.
    Using two rules has the advantage that the implementation is cleaner
    because it better separates the concerns. However it has the
    disadvantage that it's harder to set up because both a method rule and
    a class rule are needed. This also increases the potential for
    misconfiguration.
    
    The method rule has to be a MethodRule instead of a TestRule because
    only the former has access to the test object with we need to perform
    injection. This interface used to be deprecated once but doesn't seem
    to be anymore. This creates a certain risk that it will be deprectated
    again and potentially be remvoed in the future. An additional drawback
    is that MethodRule unlike TestRule can only be defined in fields and
    not methods. This is an unfortunate consequence of the implementation
    of org.junit.runners.model.TestClass. As JUnit does not do
    Field#setAccessible(true) this means that tests will have to be defined
    in public fields.
    
    Another minor issue is that tests not run because of IfProfileValue
    will still show up in the Eclipse test tree, just blank.
    
    In conclusion while the given implementation has some downsides I don't
    see any other possible implementations given the current state of
    affairs in JUnit.
    
    - Add SpringJUnitClassRule for all the class level processing
    - Add SpringJUnitMethodRule for all the method level processing
    - Add tests for the rules
    
    SPR-10217
This page is out of date. Refresh to see the latest.
View
149 spring-test/src/main/java/org/springframework/test/context/junit4/SpringJUnitClassRule.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assume.assumeTrue;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.springframework.test.annotation.ProfileValueUtils;
+import org.springframework.test.context.TestContextManager;
+
+
+/**
+ * <p>
+ * {@code SpringJUnitClassRule} is a custom {@link TestRule} which provides
+ * functionality of the <em>Spring TestContext Framework</em> to standard
+ * JUnit 4.9+ tests by means of the {@link TestContextManager} and associated
+ * support classes and annotations.
+ * </p>
+ * <p>
+ * Compared to {@link SpringJUnit4ClassRunner} the rule based JUnit support
+ * has the advantage that it is independent of the runner and can therefore
+ * be combined with existing 3rd party runners like {@code Parameterized}.
+ * </p>
+ * <p>
+ * However to achieve the same functionality as {@link SpringJUnit4ClassRunner}
+ * {@code SpringJUnitClassRule} has to be combined with
+ * {@link SpringJUnitMethodRule} as {@code SpringJUnitClassRule} only provides
+ * the class level features of {@link SpringJUnit4ClassRunner}.
+ * </p>
+ *
+ * <p>
+ * The following example shows you how to use {@code SpringJUnitClassRule}.
+ * </p>
+ * <pre><code>
+ * public class ExampleTest {
+ *
+ * @ClassRule
+ * public static final SpringJUnitClassRule CLASS_RULE = new SpringJUnitClassRule();
+ *
+ * @Rule
+ * public MethodRule methodRule = new SpringJUnitMethodRule(CLASS_RULE);
+ * }
+ * </code></pre>
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ * @see SpringJUnit4ClassRunner
+ * @see TestContextManager
+ * @see SpringJUnitMethodRule
+ */
+public class SpringJUnitClassRule implements TestRule {
+
+ // volatile since SpringJUnitMethodRule can potentially access it from a
+ // different thread depending on the runner.
+ private volatile TestContextManager testContextManager;
+
+ /**
+ * Get the {@link TestContextManager} associated with this runner.
+ * Will be {@code null} until this class is called by the JUnit framework.
+ */
+ protected final TestContextManager getTestContextManager() {
+ return this.testContextManager;
+ }
+
+
+ /**
+ * Creates a new {@link TestContextManager} for the supplied test class and
+ * the configured <em>default {@code ContextLoader} class name</em>.
+ * Can be overridden by subclasses.
+ * @param clazz the test class to be managed
+ * @see #getDefaultContextLoaderClassName(Class)
+ */
+ protected TestContextManager createTestContextManager(Class<?> clazz) {
+ return new TestContextManager(clazz, getDefaultContextLoaderClassName(clazz));
+ }
+
+
+ /**
+ * Get the name of the default {@code ContextLoader} class to use for
+ * the supplied test class. The named class will be used if the test class
+ * does not explicitly declare a {@code ContextLoader} class via the
+ * {@code &#064;ContextConfiguration} annotation.
+ * <p>The default implementation returns {@code null}, thus implying use
+ * of the <em>standard</em> default {@code ContextLoader} class name.
+ * Can be overridden by subclasses.
+ * @param clazz the test class
+ * @return {@code null}
+ */
+ protected String getDefaultContextLoaderClassName(Class<?> clazz) {
+ return null;
+ }
+
+
+ /**
+ * Check whether the test is enabled in the first place. This prevents
+ * classes with a non-matching {@code &#064;IfProfileValue} annotation
+ * from running altogether, even skipping the execution of
+ * {@code prepareTestInstance()} {@code TestExecutionListener}
+ * methods.
+ * Creates the {@link TestContextManager} and runs it's before and after
+ * class methods.
+ *
+ * @see ProfileValueUtils#isTestEnabledInThisEnvironment(Class)
+ * @see org.springframework.test.annotation.IfProfileValue
+ * @see org.springframework.test.context.TestExecutionListener
+ * @see #createTestContextManager(Class)
+ * @see TestContextManager#beforeTestClass()
+ * @see TestContextManager#afterTestClass()
+ */
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ Class<?> testClass = description.getTestClass();
+ boolean profileIsActive = ProfileValueUtils.isTestEnabledInThisEnvironment(testClass);
+ assumeTrue("required profile not active", profileIsActive);
+ testContextManager = createTestContextManager(testClass);
+ testContextManager.beforeTestClass();
+ try {
+ base.evaluate();
+ } finally {
+ testContextManager.afterTestClass();
+ // make test context manager eligible for garbage collection
+ testContextManager = null;
+ }
+
+ }
+ };
+ }
+
+}
View
97 spring-test/src/main/java/org/springframework/test/context/junit4/SpringJUnitMethodRule.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assume.assumeTrue;
+
+import java.lang.reflect.Method;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.springframework.test.annotation.ExpectedException;
+import org.springframework.test.annotation.ProfileValueUtils;
+import org.springframework.test.context.TestContextManager;
+
+
+/**
+ * <p>
+ * {@code MethodRule} is a custom {@link MethodRule} which together with
+ * {@link SpringJUnitClassRule} provides functionality of the <em>Spring
+ * TestContext Framework</em> to standard JUnit 4.9+ tests by means of the
+ * {@link TestContextManager} and associated support classes and annotations.
+ * </p>
+ * <p>
+ * The only feature not supported of {@link SpringJUnit4ClassRunner} is
+ * {@link ExpectedException}.
+ * </p>
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ * @see SpringJUnitClassRule
+ */
+public class SpringJUnitMethodRule implements MethodRule {
+
+ // Hold on to the class rule instead of the TestContextManager because
+ // the class rule "owns" the TestContextManager can releases it when no
+ // longer needed.
+ private final SpringJUnitClassRule classRule;
+
+ /**
+ * Constructs a new {@code SpringJUnitMethodRule}.
+ *
+ * @param classRule the class rule, not {@code null},
+ * the class rule has to be defined in the same test class
+ * where this {@link SpringJUnitMethodRule} instance is defined
+ */
+ public SpringJUnitMethodRule(SpringJUnitClassRule classRule) {
+ this.classRule = classRule;
+ }
+
+ /**
+ * Prepares the test instance (performs the injection) and runs the before
+ * and after test methods on the {@link TestContextManager}.
+ *
+ * @see TestContextManager#prepareTestInstance(Object)
+ * @see TestContextManager#beforeTestMethod(Object, Method)
+ * @see TestContextManager#afterTestMethod(Object, Method, Throwable)
+ */
+ @Override
+ public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ Method testMethod = method.getMethod();
+ boolean profileIsActive = ProfileValueUtils.isTestEnabledInThisEnvironment(testMethod, target.getClass());
+ assumeTrue("required profile not active", profileIsActive);
+ TestContextManager testContextManager = classRule.getTestContextManager();
+ testContextManager.prepareTestInstance(target);
+ testContextManager.beforeTestMethod(target, testMethod);
+ try {
+ base.evaluate();
+ }
+ catch (Throwable t) {
+ testContextManager.afterTestMethod(target, testMethod, t);
+ throw t;
+ }
+ testContextManager.afterTestMethod(target, testMethod, null);
+ }
+ };
+ }
+
+}
View
3  spring-test/src/main/java/org/springframework/test/context/junit4/package-info.java
@@ -1,6 +1,7 @@
/**
* <p>Support classes for ApplicationContext-based and transactional
- * tests run with JUnit 4.5+ and the <em>Spring TestContext Framework</em>.</p>
+ * tests run with JUnit 4.5+ and the <em>Spring TestContext Framework</em>.
+ * The rules need JUnit 4.9+</p>
*/
package org.springframework.test.context.junit4;
View
98 ...c/test/java/org/springframework/test/context/junit4/EnabledAndIgnoredSpringRuleTests.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.springframework.test.annotation.IfProfileValue;
+import org.springframework.test.context.TestExecutionListeners;
+
+
+/**
+ * Same as {@link EnabledAndIgnoredSpringRunnerTests} but for rule based tests.
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ * @see EnabledAndIgnoredSpringRunnerTests
+ */
+@TestExecutionListeners( {})
+public class EnabledAndIgnoredSpringRuleTests {
+
+ @ClassRule
+ public static final SpringJUnitClassRule CLASS_RULE = new SpringJUnitClassRule();
+
+ @Rule
+ public MethodRule methodRule = new SpringJUnitMethodRule(CLASS_RULE);
+
+ protected static final String NAME = "EnabledAndIgnoredSpringRunnerTests.profile_value.name";
+
+ protected static final String VALUE = "enigma";
+
+ protected static int numTestsExecuted = 0;
+
+
+ @BeforeClass
+ public static void setProfileValue() {
+ numTestsExecuted = 0;
+ System.setProperty(NAME, VALUE);
+ }
+
+ @AfterClass
+ public static void verifyNumTestsExecuted() {
+ assertEquals("Verifying the number of tests executed.", 3, numTestsExecuted);
+ }
+
+ @Test
+ @IfProfileValue(name = NAME, value = VALUE + "X")
+ public void testIfProfileValueDisabled() {
+ numTestsExecuted++;
+ fail("The body of a disabled test should never be executed!");
+ }
+
+ @Test
+ @IfProfileValue(name = NAME, value = VALUE)
+ public void testIfProfileValueEnabledViaSingleValue() {
+ numTestsExecuted++;
+ }
+
+ @Test
+ @IfProfileValue(name = NAME, values = { "foo", VALUE, "bar" })
+ public void testIfProfileValueEnabledViaMultipleValues() {
+ numTestsExecuted++;
+ }
+
+ @Test
+ public void testIfProfileValueNotConfigured() {
+ numTestsExecuted++;
+ }
+
+ @Test
+ @Ignore
+ public void testJUnitIgnoreAnnotation() {
+ numTestsExecuted++;
+ fail("The body of an ignored test should never be executed!");
+ }
+
+}
View
52 ...test/java/org/springframework/test/context/junit4/IgnoredOnClassLevelSpringRuleTests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assert.fail;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.springframework.test.annotation.IfProfileValue;
+import org.springframework.test.context.TestExecutionListeners;
+
+
+/**
+ * Same as {@link EnabledAndIgnoredSpringRuleTests} but on a class level.
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ * @see EnabledAndIgnoredSpringRuleTests
+ */
+@TestExecutionListeners( {})
+@IfProfileValue(name = EnabledAndIgnoredSpringRuleTests.NAME,
+ value = EnabledAndIgnoredSpringRuleTests.VALUE + "X")
+public class IgnoredOnClassLevelSpringRuleTests {
+
+ @ClassRule
+ public static final SpringJUnitClassRule CLASS_RULE = new SpringJUnitClassRule();
+
+ @Rule
+ public MethodRule methodRule = new SpringJUnitMethodRule(CLASS_RULE);
+
+ @Test
+ public void testIfProfileValueDisabled() {
+ fail("The body of a disabled test should never be executed!");
+ }
+
+}
View
9 ...src/test/java/org/springframework/test/context/junit4/JUnitRulesInjectionTest-context.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
+
+ <bean id="pet" class="org.springframework.tests.sample.beans.Pet">
+ <constructor-arg value="Z&#x00FC;sle" />
+ </bean>
+
+</beans>
View
88 ...g-test/src/test/java/org/springframework/test/context/junit4/JUnitRulesInjectionTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.tests.sample.beans.Pet;
+
+
+/**
+ * Verifies that injection works correctly for rule based JUnit 4 tests.
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ */
+@ContextConfiguration
+@RunWith(Parameterized.class)
+public class JUnitRulesInjectionTest {
+
+ @ClassRule
+ public static final SpringJUnitClassRule CLASS_RULE = new SpringJUnitClassRule();
+
+ @Rule
+ public MethodRule methodRule = new SpringJUnitMethodRule(CLASS_RULE);
+
+ private String parameter;
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @Autowired
+ private Pet pet;
+
+ public JUnitRulesInjectionTest(final String parameter) {
+ this.parameter = parameter;
+ }
+
+ @Test
+ public void firstMethod() {
+ assertNotNull("application context hasn't been injected", this.applicationContext);
+ assertNotNull("pet hasn't been injected", this.pet);
+ assertNotNull("parameter has not been set", this.parameter);
+ }
+
+ @Test
+ public void secondMethod() {
+ assertNotNull("application context hasn't been injected", this.applicationContext);
+ assertNotNull("pet hasn't been injected", this.pet);
+ assertNotNull("parameter has not been set", this.parameter);
+ }
+
+ @Parameters
+ public static Collection<Object[]> testData() {
+ return Arrays.asList(new Object[][] {//
+ //
+ { "first" },//
+ { "second" } //
+ });
+ }
+
+}
View
111 ...src/test/java/org/springframework/test/context/junit4/TestExecutionListenersRuleTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2004-2013 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 static org.junit.Assert.assertEquals;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.TestExecutionListener;
+import org.springframework.test.context.TestExecutionListeners;
+
+
+/**
+ * Verifies that test execution listeners work correctly for rule based
+ * JUnit 4 tests.
+ *
+ * @author Philippe Marschall
+ * @since 3.2.2
+ */
+@TestExecutionListeners(TestExecutionListenersRuleTest.InnerTestExecutionListener.class)
+public class TestExecutionListenersRuleTest {
+
+ @ClassRule
+ public static final SpringJUnitClassRule CLASS_RULE = new SpringJUnitClassRule();
+
+ @Rule
+ public MethodRule methodRule = new SpringJUnitMethodRule(CLASS_RULE);
+
+ private static int beforeTestClassRun = 0;
+ private static int prepareTestInstanceRun = 0;
+ private static int beforeTestMethodRun = 0;
+ private static int afterTestMethodRun = 0;
+ private static int afterTestClassRun = 0;
+
+ @BeforeClass
+ public static void verifyBeforeClass() {
+ assertEquals("beforeTestClassRun", 1, beforeTestClassRun);
+ assertEquals("prepareTestInstanceRun", 0, prepareTestInstanceRun);
+ assertEquals("beforeTestMethodRun", 0, beforeTestMethodRun);
+ assertEquals("afterTestMethodRun", 0, afterTestMethodRun);
+ assertEquals("afterTestClassRun", 0, afterTestClassRun);
+ }
+
+ @Test
+ public void verifyTest() {
+ assertEquals("beforeTestClassRun", 1, beforeTestClassRun);
+ assertEquals("prepareTestInstanceRun", 1, prepareTestInstanceRun);
+ assertEquals("beforeTestMethodRun", 1, beforeTestMethodRun);
+ assertEquals("afterTestMethodRun", 0, afterTestMethodRun);
+ assertEquals("afterTestClassRun", 0, afterTestClassRun);
+ }
+
+ @AfterClass
+ public static void verifyAfterClass() {
+ assertEquals("beforeTestClassRun", 1, beforeTestClassRun);
+ assertEquals("prepareTestInstanceRun", 1, prepareTestInstanceRun);
+ assertEquals("beforeTestMethodRun", 1, beforeTestMethodRun);
+ assertEquals("afterTestMethodRun", 1, afterTestMethodRun);
+ assertEquals("afterTestClassRun", 0, afterTestClassRun);
+ }
+
+
+ static class InnerTestExecutionListener implements TestExecutionListener {
+
+ @Override
+ public void beforeTestClass(TestContext testContext) throws Exception {
+ beforeTestClassRun += 1;
+ }
+
+ @Override
+ public void prepareTestInstance(TestContext testContext) throws Exception {
+ prepareTestInstanceRun += 1;
+ }
+
+ @Override
+ public void beforeTestMethod(TestContext testContext) throws Exception {
+ beforeTestMethodRun += 1;
+ }
+
+ @Override
+ public void afterTestMethod(TestContext testContext) throws Exception {
+ afterTestMethodRun += 1;
+ }
+
+ @Override
+ public void afterTestClass(TestContext testContext) throws Exception {
+ afterTestClassRun += 1;
+ }
+
+ }
+
+}
Something went wrong with that request. Please try again.