java.lang.Exception: Keine Ausnahme für ausführbare Methoden beim Ausführen von JUnits


76

Ich versuche, die JUnit an meiner Linux-Eingabeaufforderung /opt/junit/auszuführen. Sie enthält die erforderlichen JARS- (hamcrest-core-1.3.jar und junit.jar) und Klassendateien und verwende den folgenden Befehl, um die JUnit auszuführen:

java -cp hamcrest-core-1.3.jar:junit.jar:. org.junit.runner.JUnitCore  TestRunner

TestJunit-Klasse:

import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestJunit {
   @Test
   public void testAdd() {
      String str= "Junit is working fine";
      assertEquals("Junit is working fine",str);
   }
}

TestRunner:

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println("fail ho gaya"+failure.toString());
      }
      System.out.println("passed:"+result.wasSuccessful());
   }
}  

Ich erhalte die folgende Ausnahme beim Ausführen

JUnit version 4.11
.E
Time: 0.003
There was 1 failure:
1) initializationError(TestRunner)
java.lang.Exception: No runnable methods
    at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:169)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:104)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:355)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runner.Computer.getRunner(Computer.java:40)
    at org.junit.runner.Computer$1.runnerForClass(Computer.java:31)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:101)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:87)
    at org.junit.runners.Suite.<init>(Suite.java:80)
    at org.junit.runner.Computer.getSuite(Computer.java:28)
    at org.junit.runner.Request.classes(Request.java:75)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
    at org.junit.runner.JUnitCore.runMain(JUnitCore.java:96)
    at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:47)
    at org.junit.runner.JUnitCore.main(JUnitCore.java:40)

FAILURES!!!
Tests run: 1,  Failures: 1

Keine Ahnung, ich habe Anfänger-Tutorials durchlaufen. Diese Dateien wurden aus dem Tutorial selbst kopiert. Sowieso bekam meine Antwort, sqa.fyicenter.com/FAQ/JUnit/…
vipin8169


Keine der Antworten funktionierte. Es stellte sich heraus, dass ich in einem meiner Unit-Tests eine Reihe von Doppelklammern-Initialisierungen hatte ... nicht weniger auf JDK 8 ... die beim Löschen dazu führten, dass dieser Fehler verschwand! Es war so etwas wie myObject.setSomething (neues OtherObject () {{/ * Hier buchstäblich alles einfügen * /}}); Es dauerte Stunden, um dies zu finden (ich dachte immer, meine Importe brachten einen schlechten statischen Initialisierer aus einer anderen Klasse, einen schlechten Klassenlader, Reflection Garbage usw.). Ich glaube , das könnte ein JVM Fehler sein, aber haben keinen Beweis, so dass ich dies als einen Kommentar statt einer Antwort verlasse. TL; DR "Löschen Sie den {{}} Teil von Double Brace Init.
Jason D

Ich habe den gleichen Fehler erhalten und als ich den Modifikator "public" access in meiner Testklasse entfernt habe, ist der Fehler verschwunden und die Tests haben einwandfrei funktioniert. Haben Sie nicht genau untersucht, warum, sondern fügen Sie hier hinzu, nur für den Fall, dass es anderen hilft.
Levenshtein

Antworten:



77

In meinem Fall hatte ich falsches Paket importiert:

import org.testng.annotations.Test;

anstatt

import org.junit.Test;

Hüten Sie sich vor Ihrer automatischen Vervollständigung.


18
In meinem Fall war es import org.junit.jupiter.api.Test;stattdessen.
Master Chief

Ja, es kann ein falscher @ Test-Annotationsimport sein, der auf org.junit behoben wird. Test behebt das Problem. Ty!
Dominik K

Importiert org.junit.Test; bedeuten, dass Sie JUnit 4 verwenden?
wolf97084

Danke, dass du mir Zeit gespart hast! Ich hatte auch einen Testimport.
Piyush Upadhyay

20

Diese Lösung gilt für einen sehr kleinen Prozentsatz von Personen, in der Regel für Personen, die ihre eigenen JUnit-Testläufer implementieren und einen separaten ClassLoader verwenden.

Dies kann passieren , wenn Sie eine Klasse aus einem anderen Classloader geladen wird , dann versuchen , dass Test von einer Instanz von JUnitCore vom geladen zu laufen Systemklassenlader. Beispiel:

// Load class
URLClassLoader cl = new URLClassLoader(myTestUrls, null);
Class<?>[] testCls = cl.loadClass("com.gubby.MyTest");

// Run test
JUnitCore junit = new JUnitCore();
junit.run(testCls); // Throws java.lang.Exception: No runnable methods

Betrachten der Stapelverfolgung:

java.lang.Exception: No runnable methods
at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:169)
at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:104)
at org.junit.runners.ParentRunner.validate(ParentRunner.java:355)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
at org.junit.runner.JUnitCore.run(JUnitCore.java:138)

Das Problem tritt tatsächlich bei BlockJUnit4ClassRunner: 169 auf (unter der Annahme von JUnit 4.11):

https://github.com/junit-team/junit/blob/r4.11/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java#L95

Wo überprüft wird, mit welchen Methoden Anmerkungen gemacht werden @Test:

protected List<FrameworkMethod> computeTestMethods() {
    return getTestClass().getAnnotatedMethods(Test.class);
}

In diesem Fall wurde Test.classmit dem System ClassLoader (dh dem, der JUnitCore geladen hat) geladen, daher wurde technisch keine Ihrer Testmethoden mit dieser Annotation kommentiert.

Die Lösung besteht darin, JUnitCore im selben ClassLoader wie die Tests selbst zu laden.


Bearbeiten : Als Antwort auf die Frage von Benutzer 3486675 müssen Sie einen ClassLoader erstellen, der nicht an den Systemklassenlader delegiert, z.

private static final class IsolatedURLClassLoader extends URLClassLoader {
    private IsolatedURLClassLoader(URL[] urls) {
        // Prevent delegation to the system class loader.
        super(urls, null);
    }
}

Übergeben Sie eine Reihe von URLs, die alles enthalten, was Sie benötigen. Sie können dies erstellen, indem Sie den Systemklassenpfad filtern. Beachten Sie, dass Sie nicht einfach an den übergeordneten ClassLoader delegieren können, da diese Klassen dann von diesem und nicht vom ClassLoader Ihrer Testklassen geladen werden.

Dann müssen Sie den gesamten JUnit-Job von einer Klasse aus starten, die von diesem ClassLoader geladen wird. Hier wird es chaotisch. So etwas wie dieser völlige Dreck unten:

public static final class ClassLoaderIsolatedTestRunner {

    public ClassLoaderIsolatedTestRunner() {
        // Disallow construction at all from wrong ClassLoader
        ensureLoadedInIsolatedClassLoader(this);
    }

    // Do not rename.
    public void run_invokedReflectively(List<String> testClasses) throws BuildException {
        // Make sure we are not accidentally working in the system CL
        ensureLoadedInIsolatedClassLoader(this);

        // Load classes
        Class<?>[] classes = new Class<?>[testClasses.size()];
        for (int i=0; i<testClasses.size(); i++) {
            String test = testClasses.get(i);
            try {
                classes[i] = Class.forName(test);
            } catch (ClassNotFoundException e) {
                String msg = "Unable to find class file for test ["+test+"]. Make sure all " +
                        "tests sources are either included in this test target via a 'src' " +
                        "declaration.";
                throw new BuildException(msg, e);
            }
        }

        // Run
        JUnitCore junit = new JUnitCore();
        ensureLoadedInIsolatedClassLoader(junit);
        junit.addListener(...);
        junit.run(classes);
    }

    private static void ensureLoadedInIsolatedClassLoader(Object o) {
        String objectClassLoader = o.getClass().getClassLoader().getClass().getName();

        // NB: Can't do instanceof here because they are not instances of each other.
        if (!objectClassLoader.equals(IsolatedURLClassLoader.class.getName())) {
            throw new IllegalStateException(String.format(
                    "Instance of %s not loaded by a IsolatedURLClassLoader (loaded by %s)",
                    cls, objectClassLoader));
        }
    }
}

DANN müssen Sie den Läufer über Reflexion aufrufen:

Class<?> runnerClass = isolatedClassLoader.loadClass(ClassLoaderIsolatedTestRunner.class.getName());

// Invoke via reflection (List.class is OK because it just uses the string form of it)
Object runner = runnerClass.newInstance();
Method method = runner.getClass().getMethod("run_invokedReflectively", List.class);
method.invoke(...);

Das hat mir sehr geholfen. Vielen Dank! Eine Bemerkung: Es kann auch eine Option sein, den Systemklassenlader als übergeordnetes Element Ihres benutzerdefinierten Klassenladeprogramms zu verwenden. Siehe Konstruktorparameter von URLClassLoader . Auf diese Weise versucht der übergeordnete Klassenladeprogramm zuerst, die Klasse zu laden. Wenn dies nicht möglich ist, versucht der benutzerdefinierte Klassenladeprogramm, die Klasse zu laden.
Ikarus

Wie würden Sie JUnitCore im selben ClassLoader wie die Tests selbst laden?
D Malan

@ user3486675 Ich habe ein Beispiel für den sichersten Weg hinzugefügt. Es ist nicht schön.
Gub

@gubby Hallo Gubby, der obige Code wird nicht kompiliert (junit.addListener (...);) und cls ist nicht definiert. Wir stoßen ebenfalls auf dieses Problem und wollten wissen, wie es behoben werden kann.
ALM

13

Mein Controller-Test in großer Verknüpfung:

@RunWith(SpringRunner.class)
@SpringBootTest
public class TaskControllerTest {
   //...
   //tests
   //
}

Ich habe gerade "public" entfernt und es hat auf magische Weise funktioniert.


10

Ich musste die Importanweisung ändern:

import org.junit.jupiter.api.Test;

zu

import org.junit.Test;

9

Ich hatte jetzt das gleiche Problem beim Testen von Code. Das wurde im Frühjahrsstiefel wegen der @RunWithAnnotation verursacht. Ich habe benutzt:

@RunWith(SpringRunner.class)

Mit dieser Anmerkung läuft JUnit Vintage, das keine Tests finden kann und Ihnen den Fehler gibt. Ich habe das entfernt und nur JUnit Jupiter läuft und alles ist in Ordnung.


3

Ich war auch mit diesem Problem konfrontiert und konnte manchmal den Grund dafür nicht herausfinden. Später fand ich das Problem des automatischen Imports mit IDE. Das sind Importe des Programms.

Grundsätzlich habe ich Eclipse IDE verwendet. Und ich habe "org.junit.jupiter.api.Test"anstelle der erforderlichen Klasse eine falsche Klasse in das Programm "org.junit.Test".importiert. Überprüfen Sie daher Ihre Importe, bevor Sie Programme ausführen.


2

Sie können dies auch erhalten, wenn Sie versehentlich die Anmerkungen org.junit und org.junit.jupiter mischen.


2

in meinem Fall habe ich gerade //@RunWith(SpringRunner.class) deaktiviert)

und es gibt keine Ausnahme


1

Ich habe diesen Fehler erhalten, weil ich meine eigene Testsuite nicht richtig erstellt habe:

So habe ich es richtig gemacht:

Geben Sie dies ein Foobar.java:

public class Foobar{
    public int getfifteen(){
        return 15;
    }
}

Geben Sie dies ein FoobarTest.java:

import static org.junit.Assert.*;
import junit.framework.JUnit4TestAdapter;
import org.junit.Test;
public class FoobarTest {
    @Test
    public void mytest() {
        Foobar f = new Foobar();

        assert(15==f.getfifteen());
    }
    public static junit.framework.Test suite(){
       return new JUnit4TestAdapter(FoobarTest.class);
    }
}

Download junit4-4.8.2.jarIch habe den hier verwendet:

http://www.java2s.com/Code/Jar/j/Downloadjunit4jar.htm

Kompiliere es:

javac -cp .:./libs/junit4-4.8.2.jar Foobar.java FoobarTest.java

Starte es:

el@failbox /home/el $ java -cp .:./libs/* org.junit.runner.JUnitCore FoobarTest
JUnit version 4.8.2
.
Time: 0.009    
OK (1 test)

Ein Test wurde bestanden.


1

Wenn Sie Test Suite über ausführen @RunWith(Suite.class) @Suite.SuiteClasses({}) ausführen, überprüfen Sie, ob alle bereitgestellten Klassen wirklich Testklassen sind;).

In meinem Fall war eine der Klassen eine tatsächliche Implementierung, keine Testklasse. Nur ein dummer Tippfehler.


1

Ich hatte ein ähnliches Problem / einen ähnlichen Fehler beim Ausführen von JunitCore zusammen mit Junit Jupiter (Junit5) JUnitCore.runClasses(classes);nach dem Entfernen @RunWith(SpringRunner.class)und
lief mit. @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING)Ich kann das Problem für meine Tests wie in den obigen Kommentaren beschrieben beheben. https://stackoverflow.com/a/59563970/13542839


1

In meinem Fall habe ich den falschen TestImport verwendet. Der richtige warimport org.junit.Test;


0

In Eclipse musste ich verwenden New > Other > JUnit > Junit Test. Eine Java-Klasse, die mit genau demselben Text erstellt wurde, gab mir den Fehler, möglicherweise weil sie JUnit 3.x verwendete.


0

Die einfachste Lösung besteht darin, der Klasse, in der eine Initialisierungsausnahme vorliegt, eine mit Annotationen versehene @ Test-Methode hinzuzufügen.

In unserem Projekt haben wir Hauptklasse mit Grundeinstellungen. Ich habe die @ Test-Methode hinzugefügt und die Ausnahme ist verschwunden.


0

Ich konnte das Problem beheben, indem ich das Junit-JAR manuell zu meinem Projektklassenpfad hinzufügte. Der einfachste Weg, dies zu tun, war das Hinzufügen eines / lib-Verzeichnisses im Projektstamm. Dann habe ich einfach die Datei junit.jar in / lib eingefügt und die Junit-Tests beginnen für mich zu arbeiten.


0

Dasselbe habe ich mit meiner übergeordneten Test-SetUp-Klasse gesehen, die die Annotation @RunWith (SpringRunner.class) enthält und von anderen Testklassen erweitert wurde. Da es in der setUpclass keinen Test gab und Junit aufgrund der Annotation @RunWith (SpringRunner.class) versuchte, einen zu finden, wurde kein Test gefunden und eine Ausnahme ausgelöst

No runnable methods exception in running JUnits

Ich habe meine Elternklasse als abstrakt gemacht und es hat wie ein Zauber funktioniert.

Ich habe Hilfe von hier https://stackoverflow.com/a/10699141/8029525 genommen . Danke für die Hilfe @ froh42.


0

Die Lösung ist einfach, wenn Sie importieren

import org.junit.Test;

Sie müssen als Junit 4 laufen

Rechtsklick -> Ausführen als-> Testkonfiguration-> Testläufer-> als Junit 4


0

Für mich habe ich JUnit4.12und Hamcrest1.3auf dem Klassenpfad hinzugefügt und geändert import org.testng.annotations.Test;oder import org.testng.annotations.*;zu import org.junit.Test;. Es funktioniert endlich gut!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.