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

IT小君   2021-10-21T02:12:58

我试图在我的 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);
   }
}

测试运行器:

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
评论(23)
IT小君

如果您使用JUnit 4.4 核心运行器执行没有"@Test" method. 请查阅链接以获取更多信息。

礼貌 vipin8169

2021-10-21T02:12:58   回复
IT小君

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

import org.testng.annotations.Test;

代替

import org.junit.Test;

当心你的ide自动完成。

2021-10-21T02:12:58   回复
IT小君

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

当您从不同的 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将使用系统类加载器(即加载 JUnitCore 的那个)加载,因此从技术上讲,您的任何测试方法都不会使用该注释进行注释。

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


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

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

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

然后,您需要从此 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(...);
2021-10-21T02:12:58   回复
IT小君

我的控制器测试大捷径:

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

我刚刚删除了“public”并且神奇地起作用了。

2021-10-21T02:12:59   回复
IT小君

我不得不更改导入语句:

import org.junit.jupiter.api.Test;

import org.junit.Test;
2021-10-21T02:12:59   回复
IT小君

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

2021-10-21T02:12:59   回复
IT小君

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

@RunWith(SpringRunner.class)

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

2021-10-21T02:12:59   回复
IT小君

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

而且也不例外

2021-10-21T02:12:59   回复
IT小君

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

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

2021-10-21T02:12:59   回复
IT小君

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

2021-10-21T02:12:59   回复
IT小君

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

2021-10-21T02:13:00   回复
IT小君

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

2021-10-21T02:13:00   回复
IT小君

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

这是我正确执行的方法:

把这个放在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)

一项测试通过了。

2021-10-21T02:13:00   回复
IT小君

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

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

2021-10-21T02:13:00   回复
IT小君

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

2021-10-21T02:13:00   回复
IT小君

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

2021-10-21T02:13:00   回复
IT小君

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

2021-10-21T02:13:00   回复
IT小君

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

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

2021-10-21T02:13:01   回复
IT小君

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

2021-10-21T02:13:01   回复
IT小君

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

No runnable methods exception in running JUnits

我让我的父类抽象,它就像一个魅力。

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

2021-10-21T02:13:01   回复
IT小君

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

import org.junit.Test;

你必须以junit 4的身份运行

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

2021-10-21T02:13:01   回复
IT小君

对我来说,我在类路径上添加了JUnit4.12andHamcrest1.3并更改了import org.testng.annotations.Test;orimport org.testng.annotations.*;import org.junit.Test;. 它终于正常工作了!

2021-10-21T02:13:01   回复
IT小君

这里有一些启发式/经验,我正在运行一个Spring Boot项目,并且我正在让JUnit Jupiter测试与JUnit Vintage一起出现JUnit的葡萄酒的人都失败了,当我删除了公共访问修饰符的Junit的复古测试消失,其结果是实现我想要的行为。

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

||

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

为什么在 IntelliJ 中运行 TestCase 时 JUnit Jupiter 和 JUnit Vintage 分开了?

2021-10-21T02:13:01   回复