异常: 在运行 JUnit 时没有可运行的方法异常

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

测试跑者:

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
217614 次浏览

如果您使用 JUnit 4.4核心运行器来执行一个没有 "@Test" method的类,就会得到这个异常。 请参考链接获得更多信息。

感谢 vipin8169

我得到这个错误是因为我没有正确地创建我自己的测试套件:

我是这样做的:

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

Download junit4-4.8.2.jar I used the one from here:

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

编译它:

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

Run it:

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

一个测试通过了。

这个解决方案只适用于一小部分人,通常是实现自己的 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 中。


Edit : 为了回答 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 来加载。

Then you need to kick off the whole JUnit job from a class loaded by this ClassLoader. It gets messy here. Something like this utter filth below:

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

就我而言,我进口了错误的包装:

import org.testng.annotations.Test;

而不是

import org.junit.Test;

当心自动补全。

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

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

In our project we have main class with initial settings. I've added @Test method and exception has disappeared.

我的控制器在一个很大的快捷方式中测试:

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

I just removed "public" and magically it worked.

I was able to fix by manually adding the junit jar to my project classpath. The easiest way I found to do this was by adding a /lib directory in the project root. Then i just put the junit.jar inside /lib and junit tests starting working for me.

I had the same problem now with testing code. That was caused in spring boot because of the @RunWith annotation. I have used:

@RunWith(SpringRunner.class)

有了这个注释,JUnitVintage 就可以运行了,它找不到任何测试,并给出了错误。我已经删除了,只有 JUnit 木星运行,一切都很好。

如果无意中混合了 org.junit 和 org.junit.jupiter 注释,也可以得到这个结果。

我的父测试 setUp 类也遇到了同样的问题,它具有注释@RunWith (SpringRunner.class) ,并且正在被其他 testClass 扩展。 As there was not test in the setUpclass , and Junit was trying to find one due to annotation @RunWith(SpringRunner.class) ,it didn't find one and threw exception

No runnable methods exception in running JUnits

我把我的家长类作为抽象的,它工作起来像一个魅力。

我从这里得到了帮助。 谢谢你的帮助@Froh42。

解决办法很简单 if you importing

import org.junit.Test;

你必须以第四小队的身份参选

右键单击-> run as-> Test config-> Test runner-> as junit 4

对我来说,我刚刚关闭了 //@RunWith (SpringRunner.class)

也没有例外

我也遇到过这个问题,有时也没能找到同样的原因。 后来我发现自动导入问题使用 IDE。这是 进口的程序。

Basically i was using eclipse IDE. And I was importing a wrong class "org.junit.jupiter.api.Test" into the program instead of required class "org.junit.Test". Hence check your imports before running any programs.

我不得不修改进口说明:

import org.junit.jupiter.api.Test;

import org.junit.Test;

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

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

For me I added JUnit4.12 and Hamcrest1.3 on the classpath and changed import org.testng.annotations.Test; or import org.testng.annotations.*; to import org.junit.Test;. It finally works fine!

在删除 @RunWith(SpringRunner.class)和 Junit Jupiter (Junit5)之后运行 JunitCore 和 JUnitCore.runClasses(classes);时,我也遇到了类似的问题/错误
运行与 @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING)我能够解决的问题,我的测试说,在上面的意见。 Https://stackoverflow.com/a/59563970/13542839

在我的例子中,我使用了错误的 Test导入,正确的导入是 import org.junit.Test;

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

一点启发/经验在这里,我正在运行一个 弹簧靴项目,我得到的 JUnit 木星测试出现在 JUnit 复古一起。JUnit 复古测试失败了,当我移除 公众人士访问修饰符时,Junit Vintage测试消失了,结果达到了我想要的行为。

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

||

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

为什么我在 IntelliJ 中运行测试用例时 JUnit Jupiter 和 JUnit Vintage 分开了?

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

如果您正在使用 import org.Junit.jupiter.api. Test (Junit 5) and @RunWith(SpringRunner.class), SpringRunner is on Junit4, junit gets confused. Removing public before class name will work as JUnit 5抱怨公共测试类。 文件: 对于 Test 类的可见性,JUnit5比 JUnit4更宽容,JUnit4要求所有内容都是公开的。 In this context, JUnit5 test classes can have any visibility but private, however, it is recommended to use the default package visibility, which improves readability of code.

If there is,take out of pom.xml

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

当我没有向这个测试用例方法添加访问修饰符 public 时,我得到了同样的错误,在添加了它之后,它就可以工作了。我用了 JUnit 4。对于 JUnit 5,相同的测试用例不需要访问测试用例方法的说明符就可以工作。

尝试了这个方法,它在 Junit5中起作用了:

@SpringBootTest(classes = {ServletWebServerFactoryAutoConfiguration.class},
webEnvironment = RANDOM_PORT,
properties = {"spring.cloud.config.enabled=false"})
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc

我将为那些使用 Eclipse (和 Gradle)的用户再添加一个解决方案:

在我的例子中,我有一个类似下面这样的简单测试类:

package somepackage;


import static org.junit.Assert.assertFalse;


import org.junit.Test;


public class SomeTest
{
@Test
public void test_someClass_doesNotDoThing_whenCreated()
{
SomeClass someClass = new SomeClass();
        

assertFalse( "", someClass.doesThing() );
}
}


这将检查所有相关的复选框:

  • 使用了正确的导入
  • @Test annotation is present
  • 测试方法是公共的
  • 没有不同的类装入器

仍然有“不可运行方法”异常。显然,当测试项目或工作空间中的其他项目出现编译错误(与测试类无关)时,Eclipse 没有得到我怀疑容易发生的备忘录。

这个问题的解决办法是:

  • 在 Eclipse 中为整个工作区调用“ Refresh Gradle Project”(可能是可选的)
  • 在 Eclipse 中调用“ Project”-> “ Clean”

This made Eclipse understand there was a valid test method in my test class.