簡體   English   中英

java.lang.Exception:運行 JUnit 時沒有可運行方法異常

[英]java.lang.Exception: No runnable methods exception in running JUnits

I am trying to run the JUnit on my Linux command prompt /opt/junit/ contains the necessary JARS(hamcrest-core-1.3.jar and junit.jar) and class files and I am using the following command to run the JUnit:

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

TestJunit class:

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

如果您使用JUnit 4.4 核心運行器執行沒有"@Test" method的類,您將收到此異常。 請查閱鏈接以獲取更多信息。

禮貌 vipin8169

就我而言,我導入了錯誤的包:

import org.testng.annotations.Test;

代替

import org.junit.Test;

當心你的ide自動完成。

此解決方案將適用於極少數人,通常是實現自己的 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將使用系統ClassLoader(即加載 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(...);

我的控制器測試大捷徑:

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

我剛剛刪除了“public”並且神奇地起作用了。

我不得不更改導入語句:

import org.junit.jupiter.api.Test;

import org.junit.Test;

我現在在測試代碼時遇到了同樣的問題。 這是由於@RunWith注釋在spring boot 中引起的。 我用過了:

@RunWith(SpringRunner.class)

使用該注釋,JUnit Vintage 正在運行,它找不到任何測試並給出錯誤。 我已經刪除了它,只有 JUnit Jupiter 正在運行,一切都很好。

就我而言,我使用了錯誤的Test導入。 正確的是import org.junit.Test;

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

而且也不例外

我也遇到了這個問題,有時無法找出相同的原因。 后來我發現使用IDE自動導入問題。 那就是程序的導入

基本上我使用的是eclipse IDE。 我在程序中導入了錯誤的類"org.junit.jupiter.api.Test" ,而不是所需的類"org.junit.Test". 因此,在運行任何程序之前檢查您的導入。

如果您不小心混合了 org.junit 和 org.junit.jupiter 注釋,您也可以得到這個。

我收到此錯誤是因為我沒有正確創建自己的測試套件:

這是我正確執行的方法:

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

一項測試通過了。

如果您通過@RunWith(Suite.class) @Suite.SuiteClasses({})運行測試套件,請檢查所有提供的類是否真的是測試類;)。

就我而言,其中一個類是實際實現,而不是測試類。 只是一個愚蠢的錯字。

我在與 Junit Jupiter(Junit5) JUnitCore.runClasses(classes);一起運行 JunitCore 時遇到了類似的問題/錯誤JUnitCore.runClasses(classes); 刪除@RunWith(SpringRunner.class)
使用@SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING)我能夠解決我的測試問題,如上述評論中所述。 https://stackoverflow.com/a/59563970/13542839

如果用@RunWith(SpringRunner.class) 注釋的類但是我們的類不包含任何測試方法,那么我們將面臨這個問題。 解決方案:如果我們抽象我們不會得到這個,或者如果刪除 public 那么我們也不會面臨這個問題。

對我來說,替換import org.junit.jupiter.api.Test; import org.junit.Test; 有幫助。

在 Eclipse 中,我必須使用New > Other > JUnit > Junit Test 使用完全相同的文本創建的 Java 類給了我錯誤,可能是因為它使用的是 JUnit 3.x。

最簡單的解決方案是將 @Test 注釋方法添加到存在初始化異常的類中。

在我們的項目中,我們有帶有初始設置的主類。 我添加了@Test 方法,異常消失了。

我能夠通過手動將 junit jar 添加到我的項目類路徑來修復。 我發現最簡單的方法是在項目根目錄中添加一個 /lib 目錄。 然后我將 junit.jar 放在 /lib 中,junit 測試開始為我工作。

我的父測試 setUp 類也遇到了同樣的情況,該類具有 @RunWith(SpringRunner.class) 注釋並且正在被其他 testClasses 擴展。 由於 setUpclass 中沒有測試,並且 Junit 由於注釋 @RunWith(SpringRunner.class) 試圖找到一個,它沒有找到一個並拋出異常

No runnable methods exception in running JUnits

我讓我的父類抽象,它就像一個魅力。

我從這里獲得幫助https://stackoverflow.com/a/10699141/8029525 感謝@froh42 的幫助。

如果您導入,解決方案很簡單

import org.junit.Test;

你必須以junit 4的身份運行

右鍵單擊-> 運行方式-> 測試配置-> 測試運行器-> 作為 junit 4

對我來說,我在類路徑上添加了JUnit4.12Hamcrest1.3並更改了import org.testng.annotations.Test; import org.testng.annotations.*; import org.junit.Test; . 它終於正常工作了!

這里有一些啟發式/經驗,我正在運行一個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 {

為什么在 IntelliJ 中運行 TestCase 時 JUnit Jupiter 和 JUnit Vintage 分開了?

如果您使用 import org.junit.jupiter.api.Test (Junit 5) 和 @RunWith(SpringRunner.class),SpringRunner 在 Junit4 上,junit 會感到困惑。 在類名之前刪除 public 將起作用,因為 Junit 5 抱怨公共測試類。 來自文檔:JUnit5 比 JUnit4 更能容忍測試類的可見性,后者要求所有內容都是公開的。 在這種情況下,JUnit5 測試類可以具有除私有之外的任何可見性,但是,建議使用默認包可見性,這樣可以提高代碼的可讀性。

如果有,取出 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)的用戶添加另一種解決方案:

就我而言,我進行了一項簡單的測試 class ,例如:

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注釋存在
  • 測試方法是公開的
  • 無異 class 裝載機

仍然得到“無可運行方法”異常。 顯然 Eclipse 沒有收到我懷疑當工作空間中的測試項目或其他項目出現編譯錯誤(與測試類無關)時容易發生的備忘錄。

這是通過以下方式解決的:

  • 在 Eclipse 中為整個工作區調用“刷新 Gradle 項目”(可能是可選的)
  • 在 Eclipse 中調用“項目”->“清理”

這讓 Eclipse 明白在我的測試 class 中有一個有效的測試方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM