java.lang.Exception:运行JUnit时没有可运行的方法异常


78

我试图在Linux命令提示符下运行JUnit,/opt/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

dunno,正在学习初学者教程。这些文件是从教程本身复制的。无论如何,我的答案都在sqa.fyicenter.com/FAQ/JUnit/…– vipin8169 2014
6


没有答案有效。事实证明,在我的一个单元测试中,我有一排双括号初始化...在JDK 8上同样如此...删除后,导致此错误消失了!就像myObject.setSomething(new OtherObject(){{/ *在这里将字面上的任何内容* /}})一样;花了几个小时才找到它(一直认为我的导入从另一个类,错误的类加载器,反射垃圾等引入了一些错误的静态初始化器)。我相信这可能是JVM错误,但没有证据,因此我将其留为注释而不是答案。TL; DR“删除双支架初始化的{{}}一部分。
詹森d

1
我遇到了同样的错误,当我删除测试类上的“ public”访问修饰符时,该错误消失了,并且测试功能正常。还没有深入研究为什么,但是在这里添加以防万一它对其他人有帮助。
levenshtein

Answers:



81

就我而言,我导入了错误的软件包:

import org.testng.annotations.Test;

代替

import org.junit.Test;

当心您的ide自动完成功能。


18
就我而言,它是import org.junit.jupiter.api.Test;
首席酋长

是的,@ Test批注导入可以是错误的,将其修复为org.junit.Test可以解决问题。!
多米尼克·K

是否导入org.junit.Test; 表示您正在使用JUnit 4?
wolf97084 '20

感谢您节省时间!我也有testng输入。
Piyush Upadhyay

20

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

当您从其他ClassLoader加载类,然后尝试从系统类加载器加载的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将已使用系统ClassLoader加载(即,已加载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?
D Malan

@ user3486675我添加了一个最安全的方法示例。不好看
gub 2015年

@gubby您好,Gubby,以上代码未编译(junit.addListener(...);),并且未定义cls。我们也遇到了这个问题,并希望了解如何解决它。
ALM

13

我的控制器测试非常快捷:

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

我只是删除了“公共”,然后神奇地起作用了。


11

我不得不更改导入语句:

import org.junit.jupiter.api.Test;

import org.junit.Test;

9

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

@RunWith(SpringRunner.class)

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


4

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



3

我也遇到了这个问题,有时甚至无法弄清同样的原因。后来我发现使用IDE的自动导入问题。那就是进口程序的。

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


2

如果不经意间混用了org.junit和org.junit.jupiter批注,也可以得到此信息。


1

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

这是我正确执行的方法:

放入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)

一项测试通过。


1

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

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


1

JUnitCore.runClasses(classes);在删除@RunWith(SpringRunner.class)
运行之后,与Junit Jupiter(Junit5)一起运行JunitCore时,我遇到了类似的问题/错误,@SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING)我能够按照上面的评论所述解决我的测试问题。 https://stackoverflow.com/a/59563970/13542839


0

在Eclipse中,我不得不使用New > Other > JUnit > Junit Test。使用完全相同的文本创建的Java类给了我错误,可能是因为它使用的是JUnit3.x。


0

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

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


0

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


0

我的父测试setUp类也遇到了同样的问题,该类具有批注@RunWith(SpringRunner.class)并被其他testClasses扩展。由于setUpclass中没有测试,并且由于注释@RunWith(SpringRunner.class),Junit试图找到一个测试,因此没有找到一个抛出异常

No runnable methods exception in running JUnits

我把我的父班设为抽象班,它就像一个魅力。

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


0

如果导入,解决方案很简单

import org.junit.Test;

你必须以junit 4运行

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


0

对我来说,我加入JUnit4.12Hamcrest1.3在类路径上,改变import org.testng.annotations.Test;import org.testng.annotations.*;import org.junit.Test;。终于可以了!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.