java.lang.Exception: У запущених JUnits немає винятку методів, що запускаються


78

Я намагаюся запустити JUnit у своєму командному рядку Linux, що /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

не знаю, переглядав підручники для початківців. ці файли були скопійовані з самого підручника. У будь-якому випадку отримав мою відповідь, sqa.fyicenter.com/FAQ/JUnit/…
vipin8169


Жодна з відповідей не спрацювала. Виявляється, у мене був рядок ініціалізації подвійних фігурних дужок в одному з моїх модульних тестів ... на JDK 8 не менше ... що, видаливши, ця помилка зникла! Це було щось на зразок myObject.setSomething (new OtherObject () {{/ * Помістіть буквально будь-що сюди * /}}); Це знадобилося годинами (все думав, що мій імпорт приносить якийсь поганий статичний ініціалізатор з іншого класу, поганий завантажувач класів, сміття для відображення тощо). Я вважаю, що це може бути помилка JVM, але не маю доказів, тому я залишаю це як коментар замість відповіді. TL; DR "Видалити {{}} частину подвійної фігурної дужки.
Джейсон Д,

1
Я отримав ту саму помилку, і коли я видалив модифікатор доступу "public" у своєму тестовому класі, помилка зникла, і тести функціонували нормально. Не заглиблюйтесь у те, чому саме, але додайте тут лише на випадок, якщо це допоможе іншим.
levenshtein

Відповіді:


124

Ви отримаєте цей виняток, якщо використовуєте основний бігун JUnit 4.4 для виконання класу, якого немає "@Test" method. Будь ласка, зверніться за посиланням для отримання додаткової інформації.

чемність vipin8169


28
Я отримую цю помилку з Junit5, і у мене немає занять без "@Test"
Дурга Суаруп,

У моєму випадку це було пов’язано з тим, що мій метод @Before був названий setUp () замість setup ()
ben_joseph

81

У моєму випадку я імпортував неправильний пакет:

import org.testng.annotations.Test;

замість

import org.junit.Test;

Остерігайтеся свого автозаповнення.


18
У моєму випадку це було import org.junit.jupiter.api.Test;замість цього.
Майстер-начальник

Так, може бути будь-яке неправильне імпортування анотацій @Test, виправлення його в org.junit.Test вирішує проблему. Тай!
Домінік К

Імпортує org.junit.Test; означає, що ви використовуєте JUnit 4?
wolf97084

Дякуємо, що заощадили мій час! Я теж мав імпорт testng.
Піюш Упадхяй,

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, що і самі тести.


Редагувати : Відповідаючи на запитання користувача3486675, вам потрібно створити 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 ваших тестових класів.

Тоді вам потрібно розпочати всю роботу JUnit із класу, завантаженого цим ClassLoader. Тут стає безладним. Щось на зразок цієї повної бруду нижче:

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 . Таким чином, навантажувач батьківського класу спробує завантажити клас першим, лише якщо це неможливо, завантажувач спеціального класу спробує завантажити клас.
Ікар

Як би ви завантажили JUnitCore в тому ж ClassLoader, що і самі тести?
D Malan

@ user3486675 Я додав приклад найбезпечнішого способу зробити це. Це не красиво.
gub

@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анотацію. Я використав:

@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 разом з Junit Jupiter (Junit5) JUnitCore.runClasses(classes);після видалення @RunWith(SpringRunner.class)та
запуску, @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING)і я можу вирішити проблему для своїх тестів, як зазначено у вищезазначених коментарях. https://stackoverflow.com/a/59563970/13542839


0

В Eclipse мені довелося використовувати New > Other > JUnit > Junit Test. Клас Java, створений із точно таким самим текстом, дав мені помилку, можливо тому, що він використовував JUnit 3.x.


0

Найпростішим рішенням є додавання анотованого методу @Test до класу, де присутній виняток ініціалізації.

У нашому проекті ми маємо основний клас із початковими налаштуваннями. Я додав метод @Test, і виняток зник.


0

Я зміг це виправити, додавши вручну jarit до мого шляху до класу проекту. Найпростіший спосіб зробити це - додати каталог / lib в кореневій папці проекту. Тоді я просто помістив junit.jar всередину / lib і junit тести, які починають працювати для мене.


0

Я зіткнувся з тим самим з моїм батьківським тестом setUp, який має анотацію @RunWith (SpringRunner.class) і розширюється іншими testClasses. Оскільки в setUpclass не було тесту, а Junit намагався знайти його через анотацію @RunWith (SpringRunner.class), він не знайшов і видав виняток

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.12і Hamcrest1.3на шлях до класу і змінив import org.testng.annotations.Test;або import org.testng.annotations.*;на import org.junit.Test;. Нарешті це чудово працює!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.