Java.lang.Exception: pas de méthode runnable

j'essaie D'exécuter le JUnit sur mon invite de commande Linux /opt/junit/ contient les pots nécessaires(hamcrest-core-1.3.jar et junit.jar) et les fichiers de classe et je suis en utilisant la commande suivante pour exécuter la JUnit:

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

Classe TestJunit:

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);
   }
}

Lanceur:

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());
   }
}  

je suis l'exception suivante sur l'exécution de cette

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.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
33
demandé sur Eric Leschinski 2014-06-20 07:57:22

5 réponses

Vous obtiendrez cette exception, si vous utilisez le JUnit 4.4 core runner pour exécuter une classe qui n'a pas d' "@Test" method. Veuillez consulter le lien pour plus d'info.

avec la permission de vipin8169

68
répondu 4aRk Kn1gh7 2014-06-20 04:14:52

Cette solution s'appliquera à un très petit pourcentage de personnes, généralement des personnes mettant en œuvre leurs propres coureurs JUnit test et en utilisant un ClassLoader séparé.

cela peut arriver quand vous chargez une classe à partir d'un ClassLoader différent, puis tentez d'exécuter ce test à partir d'une instance de JUnitCore chargée à partir de chargeur de classe. Exemple:

// 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

en Regardant la trace de la pile:

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)

Le problème en fait se produit à BlockJUnit4ClassRunner:169 (en supposant que JUnit 4.11):

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

où il vérifie quelles méthodes sont annotées avec @Test:

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

Dans ce cas, Test.class aura été chargé avec le ClassLoader (c.-à-d. celui qui a chargé JUnitCore), donc techniquement aucune de vos méthodes d'essai n'aura été annotés avec cette annotation.


Modifier: en réponse à la question de user3486675, vous devez créer un ClassLoader qui ne délègue pas à la classe system loader, par exemple:

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

passez ceci un ensemble D'URLs qui inclut tout ce dont vous avez besoin. Vous pouvez créer ceci en filtrant le classpath système. Notez que vous ne pouvez pas simplement délégué au ClassLoader parent, parce que ces classes seraient alors chargées par cela plutôt que le ClassLoader de vos classes de test.

alors vous devez lancer tout le travail de JUnit d'une classe chargée par ce ClassLoader. Il obtient en désordre ici. Quelque chose comme cette saleté totale ci-dessous:

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));
        }
    }
}

alors, vous devez invoquer le coureur via la réflexion:

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(...);
12
répondu gubby 2015-11-03 16:58:23

dans mon cas j'ai fait importer le mauvais paquet:

import org.testng.annotations.Test;

au lieu de

import org.junit.Test;

méfiez-vous de votre ide autocomplete.

7
répondu awasik 2016-04-19 12:31:17

j'ai eu cette erreur parce que je n'ai pas créé ma propre suite de test correctement:

Voici comment je l'ai fait correctement:

Mettre cela dans Foobar.java:

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

Mettre cela dans 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);
    }
}

Télécharger junit4-4.8.2.jar j'ai utilisé l'un de ici:

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

Compiler:

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

Exécuter:

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

un test réussi.

1
répondu Eric Leschinski 2014-09-18 20:49:07

Dans Eclipse, j'ai eu à utiliser New > Other > JUnit > Junit Test. Une classe Java créée avec exactement le même texte m'a donné l'erreur, peut-être parce qu'elle utilisait JUnit 3.x.

0
répondu Noumenon 2016-12-08 14:42:42