Author: krosenvold
Date: Tue Jul 20 21:17:37 2010
New Revision: 966015

URL: http://svn.apache.org/viewvc?rev=966015&view=rev
Log:
[SUREFIRE-629] NPE when beforeClass fails

Testcase submitted by Aslak Knutsen

Added:
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTestCase.java
Modified:
    
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java

Modified: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java?rev=966015&r1=966014&r2=966015&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
 (original)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentReportingRunListener.java
 Tue Jul 20 21:17:37 2010
@@ -102,7 +102,17 @@ public abstract class ConcurrentReportin
     public void testFailure( Failure failure )
         throws Exception
     {
-        TestMethod.getThreadTestMethod().testFailure( failure );
+        getOrCreateTestMethod(failure.getDescription()).testFailure( failure );
+    }
+
+    private TestMethod getOrCreateTestMethod( Description description )
+    {
+        TestMethod threadTestMethod = TestMethod.getThreadTestMethod();
+        if (threadTestMethod != null){
+            return threadTestMethod;
+        }
+        TestSet testSet = getTestSet( description );
+        return testSet.createTestMethod( description );
     }
 
     @Override
@@ -116,7 +126,8 @@ public abstract class ConcurrentReportin
         throws Exception
     {
         TestSet testSet = getTestSet( description );
-        testSet.createTestMethod( description ).testIgnored( description );
+        TestMethod testMethod = getTestSet( description ).createTestMethod( 
description );
+        testMethod.testIgnored( description );
         testSet.incrementFinishedTests( reporterManager, reportImmediately );
     }
 

Added: 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTestCase.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTestCase.java?rev=966015&view=auto
==============================================================================
--- 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTestCase.java
 (added)
+++ 
maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTestCase.java
 Tue Jul 20 21:17:37 2010
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.apache.maven.surefire.junitcore;
+
+import junit.framework.Assert;
+import org.apache.maven.surefire.report.ConsoleReporter;
+import org.apache.maven.surefire.report.ReporterManagerFactory;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.Computer;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TestCase that expose "No tests were executed!" on Test failure using Maven 
Surefire 2.6-SNAPSHOT
+ * and the JUnit 4.7 Runner.
+ *
+ * -------------------------------------------------------
+ *  T E S T S
+ *  -------------------------------------------------------
+ *
+ *  Results :
+ *
+ *  Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
+ *
+ *  [INFO] 
------------------------------------------------------------------------
+ *  [INFO] BUILD FAILURE
+ *  [INFO] 
------------------------------------------------------------------------
+ *  [INFO] Total time: 11.011s
+ *  [INFO] Finished at: Thu Jul 15 13:59:14 CEST 2010
+ *  [INFO] Final Memory: 24M/355M
+ *  [INFO] 
------------------------------------------------------------------------
+ *  [ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-surefire-plugin:2.5:test
+ *  (default-test) on project xxxxxx: No tests were executed!  (Set 
-DfailIfNoTests=false to
+ *  ignore this error.) -> [Help 1]
+ *
+ *
+ *  <dependency>
+ *      <groupId>junit</groupId>
+ *      <artifactId>junit</artifactId>
+ *      <version>4.8.1</version>
+ *      <scope>test</scope>
+ *  </dependency>
+ *
+ *  <dependency>
+ *      <groupId>org.apache.maven.surefire</groupId>
+ *      <artifactId>surefire-booter</artifactId>
+ *      <version>2.6-SNAPSHOT</version>
+ *      <scope>test</scope>
+ *      </dependency>
+ *  <dependency>
+ *      <groupId>org.apache.maven.plugins</groupId>
+ *      <artifactId>maven-surefire-plugin</artifactId>
+ *      <version>2.6-SNAPSHOT</version>
+ *      <scope>test</scope>
+ *  </dependency>
+ *  <dependency>
+ *      <groupId>org.apache.maven.surefire</groupId>
+ *      <artifactId>surefire-junit47</artifactId>
+ *      <version>2.6-SNAPSHOT</version>
+ *      <scope>test</scope>
+ *  </dependency>
+ *
+ * @author <a href="mailto:[email protected]";>Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class MavenSurefireJUnit47RunnerTestCase
+{
+
+   /*
+    * Assumption:
+    * The ConcurrentReportingRunListener assumes a Test will be Started before 
it Fails or Finishes.
+    *
+    * Reality:
+    * JUnits ParentRunner is responsible for adding the BeforeClass/AfterClass 
statements to the
+    * statement execution chain. After BeforeClass is executed, a Statement 
that delegates to the
+    * abstract method: runChild(T child, RunNotifier notifier) is called. As 
the JavaDoc explains:
+    * "Subclasses are responsible for making sure that relevant test events 
are reported through {...@code notifier}".
+    * When a @BeforeClass fail, the child that should handle the relevant test 
events(Started, Failed, Finished)
+    * is never executed.
+    *
+    * Result:
+    * When Test Failed event is received in ConcurrentReportingRunListener 
without a Started event received first,
+    * it causes a NullPointException because there is no ClassReporter setup 
for that class yet. When this Exception
+    * is thrown from the ConcurrentReportingRunListener, JUnit catches the 
exception and reports is as a Failed test.
+    * But to avoid a wild loop, it removes the failing Listener before calling 
Failed test again. Since the
+    * ConcurrentReportingRunListener now is removed from the chain it will 
never receive the RunFinished event
+    * and the recorded state will never be replayed on the ReportManager.
+    *
+    * The End result: ReporterManager falsely believe no Test were run.
+    *                                                                          
                                                                  t 
+    */
+   @SuppressWarnings( { "unchecked", "ThrowableResultOfMethodCallIgnored" } )
+   @Test
+   public void surefireShouldBeAbleToReportRunStatusEvenWithFailingTests() 
throws Exception
+   {
+      Object[] reportDefinition = new Object[2];
+      reportDefinition[0] = ConsoleReporter.class.getName();
+      reportDefinition[1] = new Object[] {true};
+
+      List reportDefinitions = new ArrayList();
+      reportDefinitions.add(reportDefinition);
+
+      ReporterManagerFactory reporterManagerFactory = new 
ReporterManagerFactory(reportDefinitions, this.getClass().getClassLoader());
+
+      ConcurrentReportingRunListener concurrentReportingRunListener = 
ConcurrentReportingRunListener.createInstance(
+            reporterManagerFactory, false, false);
+
+      Computer computer = new Computer();
+
+      JUnitCore junitCore = new JUnitCore();
+
+      junitCore.addListener(concurrentReportingRunListener);
+
+      Result result = junitCore.run(computer, FailingTestClassTest.class);
+
+      junitCore.removeListener(concurrentReportingRunListener);
+
+      Assert.assertEquals(
+            "JUnit should report correctly number of test ran(Finished)",
+            0,
+            result.getRunCount());
+
+      // Sys.out swallowed in ConsoleReporter..
+      for(Failure failure : result.getFailures())
+      {
+         System.out.println(failure.getException().getMessage());
+      }
+
+      Assert.assertEquals(
+            "There should only be one Exception reported, the one from the 
failing TestCase",
+            1,
+            result.getFailureCount());
+
+      Assert.assertEquals(
+            "The exception thrown by the failing TestCase",
+            RuntimeException.class,
+            result.getFailures().get(0).getException().getClass());
+   }
+
+   /**
+    * Simple TestCase to force a Exception in @BeforeClass.
+    *
+    */
+   public static class FailingTestClassTest
+   {
+      @BeforeClass
+      public static void failingBeforeClass() throws Exception
+      {
+         throw new RuntimeException("Opps, we failed in @BeforeClass");
+      }
+
+      @Test
+      public void shouldNeverBeCalled() throws Exception
+      {
+         Assert.assertTrue(true);
+      }
+   }
+}
\ No newline at end of file


Reply via email to