diff --git a/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java b/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java index fd5650475169..92e0d07eb8f3 100644 --- a/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java +++ b/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java @@ -97,11 +97,20 @@ protected List computeTestMethods() { protected void collectInitializationErrors(List errors) { super.collectInitializationErrors(errors); + validateNoNonStaticInnerClass(errors); validateConstructor(errors); validateInstanceMethods(errors); validateFields(errors); } + protected void validateNoNonStaticInnerClass(List errors) { + if (getTestClass().isANonStaticInnerClass()) { + String gripe= "The inner class " + getTestClass().getName() + + " is not static."; + errors.add(new Exception(gripe)); + } + } + /** * Adds to {@code errors} if the test class has more than one constructor, * or if the constructor takes parameters. Override if a subclass requires @@ -128,8 +137,9 @@ protected void validateOnlyOneConstructor(List errors) { * parameters (do not override) */ protected void validateZeroArgConstructor(List errors) { - if (hasOneConstructor() - && !(getTestClass().getOnlyConstructor().getParameterTypes().length == 0)) { + if (!getTestClass().isANonStaticInnerClass() + && hasOneConstructor() + && (getTestClass().getOnlyConstructor().getParameterTypes().length != 0)) { String gripe= "Test class should have exactly one public zero-argument constructor"; errors.add(new Exception(gripe)); } diff --git a/src/main/java/org/junit/runners/model/TestClass.java b/src/main/java/org/junit/runners/model/TestClass.java index 891059ab821e..362a13af2360 100644 --- a/src/main/java/org/junit/runners/model/TestClass.java +++ b/src/main/java/org/junit/runners/model/TestClass.java @@ -1,5 +1,7 @@ package org.junit.runners.model; +import static java.lang.reflect.Modifier.isStatic; + import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -150,4 +152,8 @@ public List getAnnotatedFieldValues(Object test, } return results; } + + public boolean isANonStaticInnerClass() { + return fClass.isMemberClass() && !isStatic(fClass.getModifiers()); + } } diff --git a/src/test/java/org/junit/tests/AllTests.java b/src/test/java/org/junit/tests/AllTests.java index bca56f309bdb..2d459f110d44 100644 --- a/src/test/java/org/junit/tests/AllTests.java +++ b/src/test/java/org/junit/tests/AllTests.java @@ -53,6 +53,7 @@ import org.junit.tests.manipulation.FilterableTest; import org.junit.tests.manipulation.SingleMethodTest; import org.junit.tests.manipulation.SortableTest; +import org.junit.tests.running.classes.BlockJUnit4ClassRunnerTest; import org.junit.tests.running.classes.EnclosedTest; import org.junit.tests.running.classes.IgnoreClassTest; import org.junit.tests.running.classes.ParameterizedTestTest; @@ -152,6 +153,7 @@ CategoriesAndParameterizedTest.class, ParentRunnerFilteringTest.class, RuleChainTest.class, + BlockJUnit4ClassRunnerTest.class, BlockJUnit4ClassRunnerOverrideTest.class }) public class AllTests { diff --git a/src/test/java/org/junit/tests/running/classes/BlockJUnit4ClassRunnerTest.java b/src/test/java/org/junit/tests/running/classes/BlockJUnit4ClassRunnerTest.java new file mode 100644 index 000000000000..a19cd94e0c8f --- /dev/null +++ b/src/test/java/org/junit/tests/running/classes/BlockJUnit4ClassRunnerTest.java @@ -0,0 +1,33 @@ +package org.junit.tests.running.classes; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; + +public class BlockJUnit4ClassRunnerTest { + public static class OuterClass { + public class Enclosed { + @Test + public void test() { + } + } + } + + @Test + public void detectNonStaticEnclosedClass() throws Exception { + try { + new BlockJUnit4ClassRunner(OuterClass.Enclosed.class); + } catch (InitializationError e) { + List causes= e.getCauses(); + assertEquals("Wrong number of causes.", 1, causes.size()); + assertEquals( + "Wrong exception.", + "The inner class org.junit.tests.running.classes.BlockJUnit4ClassRunnerTest$OuterClass$Enclosed is not static.", + causes.get(0).getMessage()); + } + } +} \ No newline at end of file diff --git a/src/test/java/org/junit/tests/running/classes/TestClassTest.java b/src/test/java/org/junit/tests/running/classes/TestClassTest.java index c31413bed865..7b738d9f40f1 100644 --- a/src/test/java/org/junit/tests/running/classes/TestClassTest.java +++ b/src/test/java/org/junit/tests/running/classes/TestClassTest.java @@ -83,4 +83,39 @@ public void fieldsOnSubclassesShadowSuperclasses() { assertThat(new TestClass(SubclassWithField.class).getAnnotatedFields( Rule.class).size(), is(1)); } + + public static class OuterClass { + public class NonStaticInnerClass { + } + } + + @Test + public void identifyNonStaticInnerClass() { + assertThat( + new TestClass(OuterClass.NonStaticInnerClass.class) + .isANonStaticInnerClass(), + is(true)); + } + + public static class OuterClass2 { + public static class StaticInnerClass { + } + } + + @Test + public void dontMarkStaticInnerClassAsNonStatic() { + assertThat( + new TestClass(OuterClass2.StaticInnerClass.class) + .isANonStaticInnerClass(), + is(false)); + } + + public static class SimpleClass { + } + + @Test + public void dontMarkNonInnerClassAsInnerClass() { + assertThat(new TestClass(SimpleClass.class).isANonStaticInnerClass(), + is(false)); + } }