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
In my case I had wrong package imported:
import org.testng.annotations.Test;
instead of
import org.junit.Test;
Beware of your ide autocomplete.
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
My controller test in big shortcut:
#RunWith(SpringRunner.class)
#SpringBootTest
public class TaskControllerTest {
//...
//tests
//
}
I just removed "public" and magically it worked.
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(...);
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.
I had to change the import statement:
import org.junit.jupiter.api.Test;
to
import org.junit.Test;
In my case, I was using the wrong Test import. The correct one was import org.junit.Test;
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.
For me, replacing import org.junit.jupiter.api.Test; with import org.junit.Test; helped.
in my case i just disabled
//#RunWith(SpringRunner.class)
and there is no exception
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.
You can also get this if you mix org.junit and org.junit.jupiter annotations inadvertently.
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://stackoverflow.com/a/59563970/13542839
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?
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.
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.
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.
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.
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.
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 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://stackoverflow.com/a/10699141/8029525 .
Thanks for help #froh42.
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
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!
If there is,take out of pom.xml
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
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.
Tried this and it worked with Junit5:
#SpringBootTest(classes = {ServletWebServerFactoryAutoConfiguration.class},
webEnvironment = RANDOM_PORT,
properties = {"spring.cloud.config.enabled=false"})
#ExtendWith(MockitoExtension.class)
#AutoConfigureMockMvc
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.
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);
}
}
Related
I have a test class with multiple test methods that I would like to group by some criteria. For this purpose, using JUnit's #Category annotation on a method level seemed like a fine solution:
public class TestClass {
#Test
#Category(AssignmentServiceCategory.class)
public void testMethod1() {}
#Test
#Category(OtherCategory.class)
public void testMethod2() {}
}
I would like to create different run configurations in IntelliJ IDEA for those separate categories so that only the test methods annotated with certain category are executed. My configuration looks like this:
However, when I run this, all of the tests from the class where the method is declared are run, instead of only the ones annotated with specified category. Is my configuration incorrect, or does IDEA allow only class-level #Category annotations?
Versions:
IntelliJ IDEA 2018.1 (181.4203.550)
JRE: 1.8.0_152-release-1136-b20 amd64
JUnit 4.12
UPDATED
I tried to reproduce the issue and could not.
Here's my Test Class
package com.mytests.category;
import org.junit.Test;
import org.junit.experimental.categories.Category;
public class MyTest {
#Test
#Category(PerformanceTests.class)
public void testMethod1() {
System.out.println("method1");
}
#Test
#Category(RegressionTests.class)
public void testMethod2() {
System.out.println("method2");
}
}
Make sure you have the necessary interfaces. In JUnit, you need to create marker interfaces to represent the categories:
package com.mytests.category;
public interface RegressionTests {}
and
package com.mytests.category;
public interface PerformanceTests {}
Then in IntelliJ, I ran the tests once and it creates a configuration for me automatically. Then I edit the configuration
The results were as expected:
Only testMethod1 was executed.
OLDER ANSWER
Or from IntelliJ's Doc (https://www.jetbrains.com/help/idea/run-debug-configuration-junit.html)
Category Select this option if you only want to run test classes and
test methods that are annotated either with the category given with
the #IncludeCategory annotation, or a subtype of this category. Fill in the following fields:
Category Specify the desired category. Type category name, or click
browseButton and select the desired category in the dialog that opens.
Or You could create a TestSuite and specify (in there) which categories the suite is to include.
Something like
package org.mytests.category;
import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
#RunWith(Categories.class)
#Categories.IncludeCategory(RegressionTests.class)
#Suite.SuiteClasses({ClassA.class, ClassB.class, ClassC.class})
public class RegressionTestSuite {
}
I have (had) the same problem with Intellij 2020.1.2
There seems to be a bug related to what setting you select for search for tests.
If i choose in single module all the test are executed, even the ones annotated with other Categories.
If I choose any of the other options (in whole project, across module dependencies) it simply works as expected..
a question:
When I do something like:
package path.to.common.package.test;
#BeforeClass
public class CommonTestSetup {
public void setUp() {
// Setup Stiff
}
}
And the other class setup in the same package:
package path.to.common.package.test;
public class TestTest extends CommonTestSetup {
#Test
public void testGetTestReturnsCorrectStrings() {
// do asserts etc
}
}
And then executing JUnit test on testGetTestReturnsCorrectStrings I am getting an error:
org.junit.runners.model.InvalidTestClassError: Invalid test class 'org.junit.runner.manipulation.Filter':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:456)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:99)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:39)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:80)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:71)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:523)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Why is that? Does it mean JUnit 4 does not support Test classes extending a base class?
The idea behind this was to create a single SetUp base class, shared by many other test classes that need it.
Originally I even tried to have the base class in another package entirely, then moved it to the same package for testing, and got a different error (the one above).
use import org.junit.Test;
instead of import org.junit.jupiter.api.Test;
Based on the JUnit documentation:
Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class
So move the #BeforeClass annotation to the setUp method and make into a static method.
You may also check for things like
class classname {
class another class{
}
}
Keep one class in file it helps
I experienced similar ... I hopes it help someone ;-)
I have the following simple code. I have a class (TestClass) and I want to test "someMethod". There is an external static method which is called by my "someMethod".
I want to Powermock that static method to return me some dummy object.
I have the #PrepareForTest(ExternalClass.class) in the begining, but when I execute it gives the error:
The class ExternalClass not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or method level.
Please help me to point out what is wrong with the way I have used #PrepareForTest
#RunWith(PowerMockRunner.class)
#PrepareForTest(ExternalClass.class)
public class xyzTest {
#Mock
private RestTemplate restTemplate;
#Mock
private TestClass testClass;
#BeforeClass
private void setUpBeforeClass() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccessCase() {
Boolean mockResponse = true;
ResponseEntity<Boolean> response = new ResponseEntity<Boolean>(mockResponse, HttpStatus.OK);
SomeClass someClass = new SomeClass("test", "1.0.0", "someUrl", "someMetaData");
PowerMockito.mockStatic(ExternalClass.class);
Mockito.when(restTemplate.postForEntity(any(String.class), any(String.class), eq(Boolean.class))).thenReturn(response);
Mockito.when(ExternalClass.getSomeClass(any(String.class))).thenReturn(someClass);
Boolean result = testClass.someMethod("test");
Assert.isTrue(result);
Mockito.verify(restTemplate, times(1)).postForObject(any(String.class), any(String.class), any());
}
}
Make sure you add #RunWith(PowerMockRunner.class) to the top of your class as well.
::edit:: two years later...
Don't ever use PowerMockito, you shouldn't need to.
If you do need to, you have most likely broken the SOLID principles and your design is wrong.
Fix your design instead.
As with the last answer, my problem was also mixing the Test annotation from TestNG instead of Junit Test.
import org.junit.Test; // works
import org.testng.annotations.Test // did not work
Very abstruse error and I spent more than 5 hrs debugging :(
For those trying to get this working with Junit 5, If your using the powermock-module-junit4 beta release which claims to be compatible with 4+, the library will still not recognize:
import org.junit.jupiter.api.Test;
and it will throw a:
org.powermock.api.mockito.ClassNotPreparedException
when #PrepareForTest is applied on the class you want to static mock. If you want to use PowerMock, you will have to go back to Junit 4 or create a MockWrapper for your static method at this time.
PowerMock 2.0: Github Roadmap
While the top-rated answer here is correct without a doubt, this does not answer the question of why is that needed; or, for example, why the same thing would not work with adding #RunWith(MockitoJUnitRunner.class).
The thing is PowerMockRunner uses instrumentation API under the hood, via
javassist library, this allows to alter the classes, like remove final or mock static (non-compile time constants).
In the process of modifying (instrumenting) a certain class, they add an interface to that, called PowerMockModified. It is a marker interface that denotes that a certain byte-code instrumentation took place. Later in the code, they simply check if the class that you use in #PrepareForTest was actually instrumented in some way or not, via such a method:
private boolean isModifiedByPowerMock() {
return PowerMockModified.class.isAssignableFrom(this.type);
}
In turns out that PowerMockRunner does some instrumentation, while MockitoJUnitRunner does not; thus the error you get.
I had the same error, resolved this by adding
#Rule
public PowerMockRule rule = new PowerMockRule();
inside the test class.
If above answers don't work try extends PowerMockTestCase. This trick worked for me.
Example:
public class xyzTest extends PowerMockTestCase
check if import org.junit.Test; package has imported and not that api jupiter one.
I had the same error but resolved it. My problem was that I included powermock-module-junit4 but included my test annotation from TestNG instead of Junit.
I had the same error. I was using TestNG to run the tests. I had to use the following method to fix the above issue.
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
For testNG there are 2 options as follows :
Using ObjectFactory as below:
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
Test class extending extends org.powermock.modules.testng.PowerMockTestCase
My gradle was using Junit 5.
test {
useJUnitPlatform()
}
I was able to debug this. By having breakpoints in PowerMockRunner methods.
It was not invoked. Moreover JUnit 5 is not supported with PowerMockito.
Looks like JUnit5 runs without #ExtendWith.
Make sure you are using powermock2. I had this problem when I was using powermock.
Use
import org.powermock2.api.mockito.PowerMockito;
We are using EasyMock for JUnit testing of our Java application inside Eclipse. Using code similar to the below, we found a strange behaviour: when running the full test suite (Eclipse Project -> Run as -> JUnit) one test case fails reproducibly. However when running it standalone it works fine.
Interface:
package de.zefiro.java.easymockexception;
public interface Fruit {
public String fall();
}
Test class:
package de.zefiro.java.easymockexception;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
public class Newton {
private static final Fruit APPLE = createNiceMock(Fruit.class);
#BeforeClass
public static void SetUpClass() {
expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
replay(APPLE);
}
#Test
public void testGravity() {
String target = APPLE.fall();
assertTrue("Missed", target.contains("HEAD"));
}
}
Test suite:
package de.zefiro.java.easymockexception;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(value = Suite.class)
#SuiteClasses( { Newton.class } )
public class ScienceTests { }
Running all tests on the Eclipse project - i.e. both ScienceTests calling Newton as well as Newton directly - produced this exception in the above small example:
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.Easymock.getControlForLastCall(EasyMock.java:175)
There is a similar question here, but it seems to be unrelated.
And in our real testing code (bigger class, but the main actors are identical to the stripped-down example) this exception:
java.lang.IllegalStateException: void method cannot return a value
at org.easymock.internal.MocksControl.andReturn(MocksControl.java:101)
I didn't find an answer either on Google nor here on StackOverflow, but found out myself now, so in the spirit of answering your own questions I'll post my findings below. Worth mentioning is also this post I found, even though it didn't help me in this particular case: EasyMock Cause-Effect Exception Mapping
Putting Breakpoints on the line initializing APPLE and inside SetUpClass() I noticed that APPLE is called exactly once, while SetUpClass is called twice. This is due to the fact that the first reference to Newton creates the class and runs the static initializers, however JUnit calls #BeforeClass for each run of the test. In this case the test is run twice: once as a normal call and once as part of the test suite.
I didn't want to change the logic (i.e. don't use static), but instead changed the static #BeforeClass to a static initialization block:
public class Newton {
[...]
static {
expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
replay(APPLE);
}
// no #BeforeClass needed anymore
[...]
}
This solved the issue in both my simplified test above and in our real test coding.
I didn't find out what the difference was that triggered the different exception message, but the findings were the same - new was called only once, #BeforeClass was called multiple times and failed on the second run. The fix also worked on both.
Is there any way to group tests in JUnit, so that I can run only some groups?
Or is it possible to annotate some tests and then globally disable them?
I'm using JUnit 4, I can't use TestNG.
edit: #RunWith and #SuiteClasses works great. But is it possible to annotate like this only some tests in test class? Or do I have to annotate whole test class?
JUnit 4.8 supports grouping:
public interface SlowTests {}
public interface IntegrationTests extends SlowTests {}
public interface PerformanceTests extends SlowTests {}
And then...
public class AccountTest {
#Test
#Category(IntegrationTests.class)
public void thisTestWillTakeSomeTime() {
...
}
#Test
#Category(IntegrationTests.class)
public void thisTestWillTakeEvenLonger() {
...
}
#Test
public void thisOneIsRealFast() {
...
}
}
And lastly,
#RunWith(Categories.class)
#ExcludeCategory(SlowTests.class)
#SuiteClasses( { AccountTest.class, ClientTest.class })
public class UnitTestSuite {}
Taken from here: https://community.oracle.com/blogs/johnsmart/2010/04/25/grouping-tests-using-junit-categories-0
Also, Arquillian itself supports grouping:
https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/Categories.java
Do you want to group tests inside a test class or do you want to group test classes? I am going to assume the latter.
It depends on how you are running your tests. If you run them by Maven, it is possible to specify exactly what tests you want to include. See the Maven surefire documentation for this.
More generally, though, what I do is that I have a tree of test suites. A test suite in JUnit 4 looks something like:
#RunWith(Suite.class)
#SuiteClasses({SomeUnitTest1.class, SomeUnitTest2.class})
public class UnitTestsSuite {
}
So, maybe I have a FunctionTestsSuite and a UnitTestsSuite, and then an AllTestsSuite which includes the other two. If you run them in Eclipse you get a very nice hierarchical view.
The problem with this approach is that it's kind of tedious if you want to slice tests in more than one different way. But it's still possible (you can for example have one set of suites that slice based on module, then another slicing on the type of test).
To handle the globally disabling them, JUnit (4.5+) has two ways One is to use the new method assumeThat. If you put that in the #BeforeClass (or the #Before) of a test class, and if the condition fails, it will ignore the test. In the condition you can put a system property or something else that can be globally set on or off.
The other alternative is to create a custom runner which understands the global property and delegates to the appropriate runner. This approach is a lot more brittle (since the JUnit4 internal runners are unstable and can be changed from release to release), but it has the advantage of being able to be inherited down a class hierarchy and be overridden in a subclass. It is also the only realistic way to do this if you have to support legacy JUnit38 classes.
Here is some code to do the custom Runner. Regarding what getAppropriateRunnerForClass might do, the way I implemented it was to have a separate annotation that tells the custom runner what to run with. The only alternative was some very brittle copy paste from the JUnit code.
private class CustomRunner implements Runner
private Runner runner;
public CustomRunner(Class<?> klass, RunnerBuilder builder) throws Throwable {
if (!isRunCustomTests()) {
runner = new IgnoredClassRunner(klass);
} else {
runner = getAppropriateRunnerForClass(klass, builder);
}
public Description getDescription() {
return runner.getDescription();
}
public void run(RunNotifier notifier) {
runner.run(notifier);
}
}
EDIT: The #RunWith tag only works for a whole class. One way to work around that limiation is to move the test methods into a static inner class and annotate that. That way you have the advantage of the annotation with the organization of the class. But, doing that won't help with any #Before or #BeforeClass tags, you will have to recreate those in the inner class. It can call the outer class's method, but it would have to have its own method as a hook.
In JUnit 5 you can declare #Tag for filtering tests, either at the class or method level; analogous to test groups in TestNG or Categories in JUnit 4
From the javadoc :
tags are used to filter which tests are executed for a given test
plan. For example, a development team may tag tests with values such
as "fast", "slow", "ci-server", etc. and then supply a list of tags to
be used for the current test plan, potentially dependent on the
current environment.
For example you could declare a test class with a "slow" #Tag that will be inherited for all methods and override it for some methods if required :
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
#Tag("slow")
public class FooTest{
//
#Test
void loadManyThings(){
...
}
#Test
void loadManyManyThings(){
...
}
#Test
#Tag("fast")
void loadFewThings(){
...
}
}
You could apply the same logic for other test classes.
In this way test classes (and methods too) belongs to a specific tag.
As a good practice instead of copying and pasting #Tag("fast") and #Tag("slow") throughout the test classes, you can create custom composed annotations.
For example :
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
#Target({ ElementType.TYPE, ElementType.METHOD })
#Retention(RetentionPolicy.RUNTIME)
#Tag("slow")
public #interface Slow {
}
and use it as :
#Test
#Slow
void slowProcessing(){
...
}
To enable or disable test marked with a specific tag during the text execution you can rely on the maven-surefire-plugin documentation :
To include tags or tag expressions, use groups.
To exclude tags or tag expressions, use either excludedGroups.
Just configure in your pom.xml the plugin according to your requirement (example of the doc) :
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<groups>acceptance | !feature-a</groups>
<excludedGroups>integration, regression</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
For information the test goal documentation is not updated.
Try JUnit Test Groups. From documentation :
#TestGroup("integration")
public class MyIntegrationTest {
#ClassRule
public static TestGroupRule rule = new TestGroupRule();
...
}
Execute a simple test group: -Dtestgroup=integration
Execute multiple test groups: -Dtestgroup=group1,group2
Execute all test groups: -Dtestgroup=all
You can create test Suite objects that contain groups of tests. Alternatively, your IDE (like Eclipse) may have support for running all the tests contained in a given package.
You can Use Test Suite(http://qaautomated.blogspot.in/2016/09/junit-test-suits-and-test-execution.html) or you can Junit Categories(http://qaautomated.blogspot.in/2016/09/junit-categories.html) for grouping your test cases effectively.