java.lang.Exception: No runnable methods exception in running JUnits
Asked Answered
P

31

130

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);
   }
}

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

I am getting the following exception on running this

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
Paperhanger answered 20/6, 2014 at 3:57 Comment(4)
dunno, was going through beginner tutorials. these files were copied from the tutorial itself. Anyways got my answer, sqa.fyicenter.com/FAQ/JUnit/…Paperhanger
possible duplicate of java.lang.exception no runnable methods junitUjiji
None of the answers worked. Turns out I had a line of double braces initialization in one of my unit tests...on JDK 8 no less...that, when deleted, caused this error to go away! It was something like myObject.setSomething(new OtherObject() {{/*Put literally anything here*/}}); It took hours to find this (kept thinking my imports were bringing in some bad static initializer from another class, bad classloader, reflection garbage, etc). I believe this might be a JVM bug, but have no proof, so I'm leaving this as a comment instead of an answer. TL;DR "Delete the {{}} part of double brace init.Contemporaneous
I got the same error and when I removed the "public" access modifier on my test class the error disappeared and the tests functioned just fine. Have not dig into exactly why but adding here just in case it helps others.Rhombohedral
B
152

You will get this exception, if you use the JUnit 4.4 core runner to execute a class that has no "@Test" method. Kindly consult the link for more info.

courtesy vipin8169

Biscay answered 20/6, 2014 at 4:14 Comment(3)
I am getting this error with Junit5 and I don't have any classes without '@Test'Bonilla
In my case, it was due to my @Before method being named setUp() instead of setup()Zeph
I'd like to know what's the class causing the issue. I don't think I'll have to manually check hundreds of classes just because Mockito is too shy to tell meKwon
M
168

In my case I had wrong package imported:

import org.testng.annotations.Test;

instead of

import org.junit.Test;

Beware of your ide autocomplete.

Matchlock answered 19/4, 2016 at 12:31 Comment(6)
In my case it was import org.junit.jupiter.api.Test; instead.Chenille
Yeah can be any wrong @Test annotation import, fixing it to org.junit.Test resolves the problem. Ty!Repetitive
Does import org.junit.Test; mean that you are using JUnit 4?Stravinsky
Thanks for saving my time! I too had a testng import.Peritonitis
@Stravinsky Yes, org.junit.Test = JUnit 4, org.junit.jupiter.api.Test = JUnit 5Temikatemp
It solves the error or just don't do the test?Intravasation
B
152

You will get this exception, if you use the JUnit 4.4 core runner to execute a class that has no "@Test" method. Kindly consult the link for more info.

courtesy vipin8169

Biscay answered 20/6, 2014 at 4:14 Comment(3)
I am getting this error with Junit5 and I don't have any classes without '@Test'Bonilla
In my case, it was due to my @Before method being named setUp() instead of setup()Zeph
I'd like to know what's the class causing the issue. I don't think I'll have to manually check hundreds of classes just because Mockito is too shy to tell meKwon
U
49

My controller test in big shortcut:

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

I just removed "public" and magically it worked.

Unfair answered 13/6, 2019 at 9:11 Comment(4)
Which public do you mean?Pity
Me with exact the same mistake...Iconium
what's the magic behind this fix?Ule
Thanks. Removed public in front of the class, everything worked after thatReport
V
22

This solution will apply to a very small percentage of people, typically people implementing their own JUnit test runners and using a separate ClassLoader.

This can happen when you load a class from a different ClassLoader, then attempt to run that test from an instance of JUnitCore loaded from the system class loader. Example:

// 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

Looking at the stack trace:

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)

The problem actually occurs at BlockJUnit4ClassRunner:169 (assuming JUnit 4.11):

https://github.com/junit-team/junit/blob/r4.11/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java#L95

Where it checks which methods are annotated with @Test:

protected List<FrameworkMethod> computeTestMethods() {
    return getTestClass().getAnnotatedMethods(Test.class);
}

In this case, Test.class will have been loaded with the system ClassLoader (i.e. the one that loaded JUnitCore), therefore technically none of your test methods will have been annotated with that annotation.

Solution is to load JUnitCore in the same ClassLoader as the tests themselves.


Edit: In answer to the question from user3486675, you need to create a ClassLoader that doesn't delegate to the system class loader, e.g.:

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

Pass this a set of URLs that includes everything you need. You can create this by filtering the system classpath. Note that you cannot simply delegate to the parent ClassLoader, because those classes would then get loaded by that rather than the ClassLoader of your test classes.

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));
        }
    }
}

THEN, you need to invoke the runner via reflection:

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(...);
Vorfeld answered 25/4, 2015 at 13:10 Comment(4)
This helped me alot. Thanks! One remark: It may also be an option, to use the system classloader as parent of your custom classloader. See constructor parameters of URLClassLoader. This way, the parent class loader will try to load the class first, only if this is not possible, the custom class loader will attempt to load the class.Hoxsie
How would you load JUnitCore in the same ClassLoader as the tests themselves?Neomaneomah
@user3486675 I have added an example of the safest way to do it. It ain't pretty.Vorfeld
@gubby Hi Gubby, the above code does not compile (junit.addListener(...);) and cls is not defined. We are running into this issue as well and wanted to see how to resolve it.Sorgo
R
19

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)

With that annotation there is JUnit Vintage running which can't find any tests and gives you the error. I have removed that and only JUnit Jupiter is running and everything is fine.

Racoon answered 2/1, 2020 at 13:12 Comment(3)
Yup worked for me as well - I was using junit5 tests with this annotation!Chartres
Worked for me also!Corymb
Explanation: In JUnit5 @RunWith was replaced with @ExtendWith which is already included in @SpringBootTest annotation, so no need to add it.Ogpu
B
18

I had to change the import statement:

import org.junit.jupiter.api.Test;

to

import org.junit.Test;
Bannasch answered 21/4, 2020 at 14:26 Comment(0)
B
12

In my case, I was using the wrong Test import. The correct one was import org.junit.Test;

Brute answered 2/11, 2020 at 21:8 Comment(2)
Thanks, i too faced same issue.Fixing
Yeah, it's fixed but why? Can you explain a little bit?Nagy
F
8

If you are using 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 complains about public test classes. From Docs: JUnit5 is more tolerant regarding the visibilities of Test classes than JUnit4, which required everything to be public. 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.

Feeding answered 8/7, 2021 at 6:3 Comment(0)
C
7

in my case i just disabled //@RunWith(SpringRunner.class)

and there is no exception

Chapland answered 2/4, 2020 at 4:22 Comment(1)
@SpringBootTest(classes = {ServletWebServerFactoryAutoConfiguration.class}, webEnvironment = RANDOM_PORT, properties = {"spring.cloud.config.enabled=false"}) @ExtendWith(MockitoExtension.class) @AutoConfigureMockMvcEsmerolda
A
7

For me, replacing import org.junit.jupiter.api.Test; with import org.junit.Test; helped.

Aftercare answered 3/6, 2021 at 19:12 Comment(2)
This really worked for me. Thank you :) Could you please tell the reason why we had to use the other dependency?Uncork
@ImranFaruqi org.junit.jupiter.api.Test comes from JUnit 5 whereas org.junit.Test comes from an earlier major version of JUnit.Manage
P
4

I also faced this issue and failed to figure out the reason for the same for sometimes. Later i found that auto import issue using IDE. That is imports of the program.

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.

Pelaga answered 19/4, 2020 at 12:10 Comment(0)
P
4

If using jupiter, please remove @RunWith.

import org.junit.jupiter.api.Test;
import org.springframework.test.context.junit4.SpringRunner;

//@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class DepartmentServiceTests {
    @Autowired
    DepartmentService service;
    @MockBean
    DepartmentRepository repository;
    @Test
    public void findOneByIdTest(){
        int id = 1;
        Department expected = new Department(1,"401E","AAC01","DL","1");
        when(repository.findOneById(id)).thenReturn(expected);
        Department actual = service.findOneById(id);
        assertEquals(expected, actual);
    }
}
Preindicate answered 13/2, 2023 at 21:17 Comment(0)
A
3

After hundreds of test through netbeans unitary test with JUnit, I realized this:

if you add libraries - such as Junit and Hamcrest - AFTER creating Testing for existing class, your testing class will get No runnable methods exception in running JUnits. This is because of default imports:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

Instead, should be:

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

Hope junior developers with this silly problem as me, could have some peace after my comment...

Amling answered 2/6, 2023 at 9:6 Comment(0)
T
2

You can also get this if you mix org.junit and org.junit.jupiter annotations inadvertently.

Textualism answered 29/1, 2020 at 22:17 Comment(0)
L
2

I had similar issue/error while running JunitCore along side with Junit Jupiter(Junit5) JUnitCore.runClasses(classes); after removing @RunWith(SpringRunner.class) and
ran with @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING) i am able to resolve the issue for my tests as said in the above comments. https://mcmap.net/q/173142/-java-lang-exception-no-runnable-methods-exception-in-running-junits

Lydgate answered 16/7, 2020 at 10:59 Comment(0)
F
2

A bit of heuristic/experience here, I am running a Spring Boot project, and I was getting JUnit Jupiter tests appearing alongside JUnit Vintage. The JUnit Vintage ones were failing, when I removed the public access modifier the Junit Vintage tests disappeared, as a result achieving the behaviour I wanted.

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

||

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

Why were JUnit Jupiter and JUnit Vintage separated When I Running TestCase in IntelliJ?

Flasket answered 21/5, 2021 at 7:50 Comment(0)
U
1

I got this error because I didn't create my own test suite correctly:

Here is how I did it correctly:

Put this in Foobar.java:

public class Foobar{
    public int getfifteen(){
        return 15;
    }
}

Put this in 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

Compile it:

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)

One test passed.

Underfur answered 18/9, 2014 at 20:49 Comment(0)
P
1

If you're running test Suite via @RunWith(Suite.class) @Suite.SuiteClasses({}) check if all provided classes are really test classes ;).

In my case one of the classes was an actual implementation, not a test class. Just a silly typo.

Phytogenesis answered 3/6, 2020 at 10:8 Comment(0)
E
1

if the class annotated with @RunWith(SpringRunner.class) But we class doesn't contain any test methods then we will face this issue. Solution: if we make to abstract we will not get this or if remove public then also we will not face this issue.

Eurypterid answered 1/2, 2021 at 14:53 Comment(0)
C
1

Just replace jupiter Test annotation to junit (org.junit) annotation

Enjoy your coding :)

Campion answered 17/3, 2023 at 9:10 Comment(0)
C
0

In Eclipse, I had to use New > Other > JUnit > Junit Test. A Java class created with the exact same text gave me the error, perhaps because it was using JUnit 3.x.

Cataclinal answered 8/12, 2016 at 14:42 Comment(0)
C
0

The simplest solution is to add @Test annotated method to class where initialisation exception is present.

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

Corfam answered 15/12, 2018 at 14:19 Comment(0)
L
0

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.

Lin answered 8/8, 2019 at 13:44 Comment(0)
M
0

I faced the same with my parent test setUp class which has annotation @RunWith(SpringRunner.class) and was being extended by other testClasses. 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

I made my parent class as abstract and it worked like a charm .

I took help from here https://mcmap.net/q/175222/-junit-how-to-avoid-quot-no-runnable-methods-quot-in-test-utils-classes . Thanks for help @froh42.

Middlings answered 14/2, 2020 at 6:37 Comment(0)
T
0

the solution is simple if you importing

import org.junit.Test;

you have to run as junit 4

right click ->run as->Test config-> test runner-> as junit 4

Trabzon answered 4/3, 2020 at 13:22 Comment(0)
R
0

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!

Regeniaregensburg answered 25/6, 2020 at 21:56 Comment(0)
D
0

If there is,take out of pom.xml

       <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
Disconnected answered 20/10, 2021 at 21:5 Comment(0)
H
0

I got the same error when I missed to add access modifier public to this test-case-method, after added it works. I used JUnit 4. For Junit 5, same test-case works without access specifier to test-case-method.

Haiku answered 12/1, 2022 at 8:12 Comment(0)
E
0

Tried this and it worked with Junit5:

@SpringBootTest(classes = {ServletWebServerFactoryAutoConfiguration.class},
        webEnvironment = RANDOM_PORT,
        properties = {"spring.cloud.config.enabled=false"})
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc
Esmerolda answered 7/6, 2022 at 14:20 Comment(0)
M
0

I am going to add one more solution for those using Eclipse (and Gradle):

In my case I had a trivial test class such as this one:

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

This checks all the relevant checkboxes:

  • Correct imports are used
  • @Test annotation is present
  • Test method is public
  • No different class loader

Still got the "No runnable methods" exception. Apparently Eclipse didn't get the memo which I suspect is prone to occurring when either the test project or some other project in the work space has compilation errors (irrelevant to the test class).

This was resolved by:

  • Calling "Refresh Gradle Project" in Eclipse for the entire workspace (possibly optional)
  • Calling "Project" -> "Clean" in Eclipse

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

Medan answered 21/9, 2022 at 9:33 Comment(0)
M
0

If you use JUnit5 and command, maybe because you missed the target/test-classes in your classpath. My complete command is as belowing

java -jar C:\Libraries\maven-3.5.0\lib\junit-platform-console-standalone-1.10.0.jar "target/classes;target/test-classes;/some .jars"  --select-class "relative path to the test class"

Good luck!

Mohun answered 20/3 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.