【问题标题】:java.lang.Exception: No runnable methods exception in running JUnitsjava.lang.Exception:运行 JUnit 时没有可运行方法异常
【发布时间】:2014-08-10 18:21:03
【问题描述】:

我正在尝试在我的 Linux 命令提示符 /opt/junit/ 上运行 JUnit,其中包含必要的 JARS(hamcrest-core-1.3.jar 和 junit.jar)和类文件,我正在使用以下命令运行 JUnit:

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

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

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

我在运行时遇到以下异常

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

【问题讨论】:

  • 不知道,正在学习初学者教程。这些文件是从教程本身复制的。无论如何得到了我的答案,sqa.fyicenter.com/FAQ/JUnit/…
  • 所有答案均无效。原来我在我的一个单元测试中有一行双括号初始化......在JDK 8上同样如此......当删除时,导致这个错误消失了!它类似于 myObject.setSomething(new OtherObject() {{/*Put 任何东西*/}});花了好几个小时才找到这个(一直认为我的导入从另一个类中引入了一些糟糕的静态初始化程序、错误的类加载器、反射垃圾等)。我相信这 可能 是一个 JVM 错误,但没有证据,所以我将其作为评论而不是答案。 TL;DR "删除双括号初始化的 {{}} 部分。
  • 我遇到了同样的错误,当我在测试类上删除“public”访问修饰符时,错误消失了,测试运行正常。没有深入研究原因,只是在这里添加以防万一它对其他人有帮助。

标签: java junit ubuntu-12.04 junit4


【解决方案1】:

如果您使用 JUnit 4.4 核心运行程序 执行没有"@Test" method 的类,您将收到此异常。 Kindly consult the link for more info.

礼貌 vipin8169

【讨论】:

  • 我在使用 Junit5 时遇到此错误,并且我没有任何没有“@Test”的课程
  • 在我的例子中,这是由于我的 @Before 方法被命名为 setUp() 而不是 setup()
【解决方案2】:

我收到此错误是因为我没有正确创建自己的测试套件:

这是我正确的做法:

把这个放到Foobar.java:

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

把这个放到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);
    }
}

下载junit4-4.8.2.jar我用的是这里的:

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

编译:

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

运行它:

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

一项测试通过。

【讨论】:

    【解决方案3】:

    此解决方案将适用于极少数人,通常是实现自己的 JUnit 测试运行器并使用单独的 ClassLoader 的人。

    当您从不同的 ClassLoader 加载一个类,然后尝试从从 system 类加载器加载的 JUnitCore 实例运行该测试时,可能会发生这种情况。示例:

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

    查看堆栈跟踪:

    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)
    

    问题实际发生在 BlockJUnit4ClassRunner:169(假设 JUnit 4.11):

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

    它检查哪些方法被@Test注解:

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

    在这种情况下,Test.class 将使用 system 类加载器(即加载 JUnitCore 的类加载器)加载,因此从技术上讲,您的任何测试方法都不会使用该注释进行注释。

    解决方案是将 JUnitCore 加载到与测试本身相同的 ClassLoader 中。


    编辑:在回答 user3486675 的问题时,您需要创建一个不委托给系统类加载器的 ClassLoader,例如:

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

    传递一组包含您需要的所有内容的 URL。您可以通过过滤系统类路径来创建它。请注意,您不能简单地委托给父 ClassLoader,因为这些类将由它加载,而不是由您的测试类的 ClassLoader 加载。

    然后你需要从这个 ClassLoader 加载的类中启动整个 JUnit 作业。这里变得乱七八糟。像下面这种彻头彻尾的污秽:

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

    那么,你需要通过反射调用运行器:

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

    【讨论】:

    • 这对我帮助很大。谢谢!一句话:也可以选择使用系统类加载器作为自定义类加载器的父级。请参阅URLClassLoader 的构造函数参数。这样,父类加载器将首先尝试加载该类,只有当这不可能时,自定义类加载器才会尝试加载该类。
    • 如何在与测试本身相同的 ClassLoader 中加载 JUnitCore?
    • @user3486675 我添加了一个最安全的方法示例。不漂亮。
    • @gubby 嗨 Gubby,上面的代码无法编译 (junit.addListener(...);) 并且没有定义 cls。我们也遇到了这个问题,想看看如何解决。
    【解决方案4】:

    在我的情况下,我导入了错误的包:

    import org.testng.annotations.Test;
    

    而不是

    import org.junit.Test;
    

    小心你的 ide 自动完成功能。

    【讨论】:

    • 在我的例子中是import org.junit.jupiter.api.Test;
    • 是的,@Test 注释导入可能有任何错误,将其修复为 org.junit.Test 即可解决问题。泰!
    • 是否导入 org.junit.Test;表示您使用的是 JUnit 4?
    • 感谢您节省了我的时间!我也有一个 testng 导入。
    • @wolf97084 是的,org.junit.Test = JUnit 4,org.junit.jupiter.api.Test = JUnit 5
    【解决方案5】:

    在 Eclipse 中,我必须使用 New &gt; Other &gt; JUnit &gt; Junit Test。使用完全相同的文本创建的 Java 类给了我错误,可能是因为它使用的是 JUnit 3.x。

    【讨论】:

      【解决方案6】:

      最简单的解决方案是将@Test注解的方法添加到存在初始化异常的类中。

      在我们的项目中,我们有带有初始设置的主类。我添加了@Test 方法,异常消失了。

      【讨论】:

        【解决方案7】:

        我的控制器在大捷径测试:

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

        我刚刚删除了“public”,它神奇地起作用了。

        【讨论】:

        • 你是指哪个public
        • 我犯了完全相同的错误......
        【解决方案8】:

        我能够通过手动将 junit jar 添加到我的项目类路径来修复。我发现最简单的方法是在项目根目录中添加 /lib 目录。然后我把 junit.jar 放在 /lib 中,junit 测试开始为我工作。

        【讨论】:

          【解决方案9】:

          我现在在测试代码时遇到了同样的问题。这是由于 @RunWith 注释在 Spring Boot 中引起的。我用过:

          @RunWith(SpringRunner.class)
          

          使用该注释,JUnit Vintage 正在运行,它找不到任何测试并给您错误。我已经删除了它,只有 JUnit Jupiter 正在运行,一切都很好。

          【讨论】:

          • 是的,对我也有用——我在这个注解中使用了 junit5 测试!
          • 也为我工作!
          【解决方案10】:

          如果你不小心混合了 org.junit 和 org.junit.jupiter 注释,你也可以得到这个。

          【讨论】:

            【解决方案11】:

            我的父测试设置类也面临同样的问题,该类具有注释 @RunWith(SpringRunner.class) 并且正在被其他测试类扩展。 由于 setUpclass 中没有测试,而 Junit 由于注释 @RunWith(SpringRunner.class) 试图找到一个,它没有找到一个并抛出异常

            No runnable methods exception in running JUnits

            我将我的父类设置为抽象类,它的作用就像一个魅力。

            我从https://stackoverflow.com/a/10699141/8029525 那里得到了帮助。 感谢@froh42 的帮助。

            【讨论】:

              【解决方案12】:

              解决方法很简单 如果你导入

              import org.junit.Test;
              

              你必须以 junit 4 身份运行

              右键->运行方式->测试配置->测试运行器->作为junit 4

              【讨论】:

                【解决方案13】:

                就我而言,我只是禁用了 //@RunWith(SpringRunner.class)

                也不例外

                【讨论】:

                  【解决方案14】:

                  我也遇到过这个问题,但有时无法找出原因。 后来我发现使用IDE自动导入问题。那是程序的导入

                  基本上我使用的是 Eclipse IDE。而且我将错误的类 "org.junit.jupiter.api.Test" 导入程序而不是必需的类 "org.junit.Test". 因此在运行任何程序之前检查您的导入。

                  【讨论】:

                    【解决方案15】:

                    我不得不更改导入语句:

                    import org.junit.jupiter.api.Test;
                    

                    import org.junit.Test;
                    

                    【讨论】:

                      【解决方案16】:

                      如果您通过@RunWith(Suite.class) @Suite.SuiteClasses({}) 运行测试套件,请检查是否所有提供的类都是真正的测试类;)。

                      在我的例子中,其中一个类是一个实际的实现,而不是一个测试类。只是一个愚蠢的错字。

                      【讨论】:

                        【解决方案17】:

                        我在类路径中添加了JUnit4.12Hamcrest1.3,并将import org.testng.annotations.Test;import org.testng.annotations.*; 更改为import org.junit.Test;。终于可以正常使用了!

                        【讨论】:

                          【解决方案18】:

                          在删除 @RunWith(SpringRunner.class)
                          @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING) 一起运行我能够解决我的测试问题,如上述cmets 所述。 https://stackoverflow.com/a/59563970/13542839

                          【讨论】:

                            【解决方案19】:

                            就我而言,我使用了错误的 Test 导入。正确的是import org.junit.Test;

                            【讨论】:

                            • 谢谢,我也遇到了同样的问题。
                            • 是的,它已修复,但为什么呢?能稍微解释一下吗?
                            【解决方案20】:

                            如果类用@RunWith(SpringRunner.class)注解但是我们的类不包含任何测试方法那么我们将面临这个问题。 解决方案:如果我们制作 abstract 我们不会得到这个,或者如果删除 public 那么我们也不会遇到这个问题。

                            【讨论】:

                              【解决方案21】:

                              这里有一点启发式/经验,我正在运行一个 Spring Boot 项目,并且我得到 JUnit Jupiter 测试与 JUnit Vintage 一起出现>。 JUnit Vintage 失败了,当我删除 public 访问修饰符时,Junit Vintage 测试消失了,结果实现了我想要的行为。

                              @RunWith(SpringRunner.class)
                              @SpringBootTest
                              @ActiveProfiles(profiles = {"test"})
                              public class TestSuiteName {
                              

                              ||

                              @RunWith(SpringRunner.class)
                              @SpringBootTest
                              @ActiveProfiles(profiles = {"test"})
                              class TestSuiteName {
                              

                              Why were JUnit Jupiter and JUnit Vintage separated When I Running TestCase in IntelliJ?

                              【讨论】:

                                【解决方案22】:

                                对我来说,用import org.junit.Test; 替换import org.junit.jupiter.api.Test; 很有帮助。

                                【讨论】:

                                  【解决方案23】:

                                  如果您使用 import org.junit.jupiter.api.Test (Junit 5) 和@RunWith(SpringRunner.class),SpringRunner 在 Junit4 上,junit 很困惑。 在类名之前删除 public 将作为 Junit 5 抱怨公共测试课程。 从文档: JUnit5 在测试类的可见性方面比 JUnit4 更宽容,JUnit4 要求所有内容都是公开的。 在这种情况下,JUnit5 测试类可以具有除私有之外的任何可见性,但是,建议使用默认的包可见性,这样可以提高代码的可读性。

                                  【讨论】:

                                    【解决方案24】:

                                    如果有,取出pom.xml

                                           <exclusions>
                                                <exclusion>
                                                    <groupId>org.junit.vintage</groupId>
                                                    <artifactId>junit-vintage-engine</artifactId>
                                                </exclusion>
                                            </exclusions>
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2016-05-25
                                      • 2011-03-22
                                      • 2018-08-05
                                      相关资源
                                      最近更新 更多