PowerMock ECLEmma coverage issue - java

We are using EasyMock and PowerMock with JUnit. The coverage tool used is ECLEmma. With EasyMock, it shows the coverage properly in green (as covered). However, for the code that is unit tested with PowerMock, the coverage is shown in red (uncovered). Have read similar questions on the web. However, just wanted to check if there is a solution for this.
Thanks
Venkatesh

Yes, there is a solution for this:
First you will have to add this maven dependency:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule-agent</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
Then, instead of using this annotation #RunWith(PowerMockRunner.class), just add a #Rule in the Test class like this:
public class Test {
#Rule
public PowerMockRule rule = new PowerMockRule();
you can find more in this blog Make EclEmma test coverage work with PowerMock

It's a known problem : https://github.com/jayway/powermock/issues/422
And it has been for a long time, it won't be fixed anytime soon.
I suggest you use eCobertura instead.

This has worked in most cases in my project:
#Rule
public PowerMockRule rule = new PowerMockRule();
static {
PowerMockAgent.initializeIfNeeded();
}
Remove/Comment #RunWith(PowerMockRunner.class) & include following imports after adding powermock-module-javaagent-1.6.5.jar in your classpath:
import org.junit.Rule;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.powermock.modules.agent.PowerMockAgent;
Now right click->Coverage As->Coverage Configurations and add following lines in Arguments:
-ea -noverify -javaagent:path/to/powermock-module-javaagent-1.6.5.jar
Click Apply->Coverage.
Also note that #Before would not work in this case so you have to add all the stuffs in the methods marked with #Test from the method marked with #Before.

We have a static classes to mock. With mocking static classes, eclEmma code coverage plugin is not working in Eclipse. So what we did is, so placed #RunWith(JUnit4.class) (Instead of #RunWith(PowerMockRunner.class) ) before class and placed following lines inside class
static {
PowerMockAgent.initializeIfNeeded();
}
#Rule
public PowerMockRule rule = new PowerMockRule();
Compiled the class and ran the test class. Code coverage is working for class. This change is only in Eclipse IDE.
After writing test cases, we reverted code back to normal. Placed #RunWith(PowerMockRunner.class) instead of #RunWith(JUnit4.class) and commented above static code and powermockrule lines.

I have managed to generate PowerMock coverage with Jacoco, using powermock-module-javaagent.
Just make sure you put powermock agent after jacoco agent:
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>true</useSystemClassLoader>
<argLine>${jacocoArgLine} -javaagent:${settings.localRepository}/org/powermock/powermock-module-javaagent/${powermock.version}/powermock-module-javaagent-${powermock.version}.jar -noverify</argLine>
...
If you want to see an example, take a look at this project: https://github.com/jfcorugedo/sonar-scanner
Here you can see that sonar takes into account static methods and new statements mocked by PowerMock:
If you want to mock newstatements make sure you use PowerMockRule instead of PowerMockRunner.
Take a look at this test

Updating powermock version fix my issue below is maven dependency of supported version
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule-agent</artifactId>
<version>1.7.3</version>
<scope>test</scope>
</dependency>
Hope this helps !!!

I was facing the same issue. So, I updated the powerMockito version. Now I am using Power mock version 1.7.4 and Jacoco version 0.8.5. It's even working on eclipse also.

Here is some more detailed answer with full class.
couple of points to note:
I had to use spy instead of mockStatic
I had to move #PrepareForTest to method level.
As someone mentioned in other answers I also had to add following dependency
org.powermock:powermock-module-junit4-rule-agent:2.0.9
Below is my full class code for reference:
import java.util.ArrayList;
import java.util.Arrays;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.agent.PowerMockAgent;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.opensource.dummy.config.DummyConfig;
import org.opensource.dummy.data.builder.DataBuilder;
import org.opensource.dummy.model.SampleRequest;
import org.opensource.dummy.model.SampleType;
import org.opensource.dummy.model.Item;
import org.opensource.dummy.model.RequestType;
#RunWith(JUnit4.class)
public class MockedDataSearchServiceHelperTest {
static {
PowerMockAgent.initializeIfNeeded();
}
#Rule
public PowerMockRule rule = new PowerMockRule();
#PrepareForTest({ DummyConfig.class })
#SuppressWarnings("unchecked")
#Test
public void testSearchResponseValid() throws Exception {
Item Item = DataBuilder.createItem("2024-01-24", "2024-12-25", "61ef8faebec3bb72fbcf336d", null);
SampleRequest sampleRequest = DataBuilder.createSampleRequest(Arrays.asList(Item),
DataBuilder.createDeliveryMetrics(1), null, RequestType.ITEM);
BoolQueryBuilder boolQueryBuilder = DataSearchServiceHelper.createCustomQuery(sampleRequest, Item);
SearchRequestBuilder searchRequestBuilder = PowerMockito.mock(SearchRequestBuilder.class);
ActionFuture<SearchResponse> actionFuture = PowerMockito.mock(ActionFuture.class);
Client client = PowerMockito.mock(Client.class);
PowerMockito.spy(DummyConfig.class);
PowerMockito.doReturn(client).when(DummyConfig.class, "getClient");
Mockito.when(client
.prepareSearch(new String[] { "dummy" }))
.thenReturn(searchRequestBuilder);
Mockito.when(searchRequestBuilder.setIndicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN))
.thenReturn(searchRequestBuilder);
Mockito.when(searchRequestBuilder.setQuery(Mockito.any(QueryBuilder.class))).thenReturn(searchRequestBuilder);
Mockito.when(searchRequestBuilder.execute()).thenReturn(actionFuture);
Mockito.when(actionFuture.actionGet()).thenReturn(new SearchResponse(null, null, 0, 0, 0, 0, null, null));
SearchResponse searchResponse = DataSearchServiceHelper.getSearchResponse(
new String[] { "dummy" },
boolQueryBuilder, DataBuilder.createDeliveryMetrics(1), RequestType.ITEM);
Assert.assertNotNull(searchResponse);
}
}
I hope this helps to someone.

For mocking static classes, using #RunWith(PowerMockRunner.class) and running the "Coverage As JUnit Test" on Eclipse does show covered code as uncovered and it clearly does seem like an issue.
To add to the solutions above, in a maven project, you can try this..
In the root pom.xml, for report generation, add html as a format in cobertura-maven-plugin. Below is the way it looks.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
</plugin>
Then, go to the module where your class resides and open target/site/cobertura/index.html file in Eclipse Web Browser or in the one of your choice. You can find the coverage information there.

Related

Unable to run any Junit4 tests - InvalidTestClassError: Invalid test class

I am trying to run Junit4 tests and I am unable to run it. I have the following dependency installed
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
My test class looks like this
package model.validators;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
class UserValidatorTest {
#Test
public void shouldReturnTrueForValidPhoneNumbers() {
List<String> phoneNumbers = Arrays.asList(
"9876543210",
"7777543210"
);
boolean result = UserValidator.validateUserPhoneNumbers(phoneNumbers);
Assert.assertTrue(result);
}
}
When I try to run this test, I get the following error
org.junit.runners.model.InvalidTestClassError: Invalid test class 'model.validators.UserValidatorTest':
I am using IntellijIdea. Any idea what is going wrong here ? TIA
Tried changing dependencies, reloading maven project, setting the correct classpath in Junit Run configurations
I can see that your class UserValidatorTest is not public. On making your class public, you will be able to run the tests.
package model.validators;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
public class UserValidatorTest {
#Test
public void shouldReturnTrueForValidPhoneNumbers() {
List<String> phoneNumbers = Arrays.asList(
"9876543210",
"7777543210"
);
boolean result = UserValidator.validateUserPhoneNumbers(phoneNumbers);
Assert.assertTrue(result);
}
}
JUnit4 requires everything to be public.
JUnit5 is more tolerant regarding the visibilities of Test classes (Test classes, test methods, and lifecycle methods are not required to be public, but they must not be private).
SonarLint Rule description:
In this context (JUnit5), it is recommended to use the default package visibility, which improves the readability of code.

Spring Boot - Rest Assured methods not found

I have a REST API built with Spring Boot.
I am attempting to use Rest-Assured test framework, however I can't seem to get it to work.
I am using the guide from Here
get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));
And have added the dependencies to my maven project.
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
However, It doesn't seem to import the required classes and just prompts me to create a new "get()" method.
My Test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(Application.class)
#WebIntegrationTest
public class DemoControllerTest {
#Test
public void test() {
get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));
}
}
What am I missing?
What am I missing?
A simple static import, that's missing! In order to resolve the get static method, just use the following static import:
import static com.jayway.restassured.RestAssured.get;
I had similar issue. What I did (using new version 3.0.2):
import io.restassured.RestAssured.*;
import io.restassured.matcher.RestAssuredMatchers.*;
import org.hamcrest.Matchers.*;
Instead of:
import static io.restassured.RestAssured.*;
import static io.restassured.matcher.RestAssuredMatchers.*;
import static org.hamcrest.Matchers.*;
So I had same issue couldnt find the methods ...

How to unset environment variable before testing in maven

I have some unit test which depends on environment variable.
I'd like to unset these environment variable before testing using maven.
Question: How can I achieve that?
Unfortunately, in this case you cannot use the environmentVariables option of the Maven Surefire Plugin, mainly because it would only work to add new environment variables but not override (or reset, which is actually equals to override to empty value) an existing variable.
Also note: an ant run wrapped in Maven and executed before the test would not work either.
The proposed solution is based on Java, especially on this approach proposed in another SO post. Although not advisable for application code, this hack may be acceptable for test code.
You could add the following class to your test code (under src/test/java):
package com.sample;
import java.lang.reflect.Field;
import java.util.Map;
public class EnvHack {
#SuppressWarnings("unchecked")
public static void resetEnvironmentVariable(String name, String value) throws Exception {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.put(name, value);
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass
.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
cienv.put(name, value);
}
public static void main(String[] args) throws Exception {
resetEnvironmentVariable("test_prop", "test_value");
}
}
The class above is basically hacking Java API to change in memory the values of the environment variables. As such, they can be set to different values, reset and even unset actually (remove it from the map).
Since the class is now part of your test code, you have several options:
Use the class in the #Before methods (or #BeforeClass, with a certain difference) of a certain JUnit test case (before every JUnit method of the concerned class)
Use it within a JUnit test method (custom and narrowed usage)
Run its main method before any executed JUnit test (in a more global way) as explained below (and probably answering the question, even though other scenarios are also worth to mention, imho).
Let's have a look at each possible solution.
Use the class in the #Before methods of a certain JUnit test case
package com.sample;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MainTest {
#Before
public void init() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value");
}
#Test
public void testEnvProperty() throws Exception {
String s = System.getenv("test_prop");
Assert.assertEquals(s, "test_value");
}
}
This solution can be used per test class and when a set of tests (methods) share the same requirements (suggestion: if they don't, it may be an hint, probably some method should be moved out).
Use it within a JUnit test method
package com.sample;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MainTest {
#Before
public void init() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value");
}
#Test
public void testEnvProperty() throws Exception {
EnvHack.resetEnvironmentVariable("test_prop", "test_value2");
String s = System.getenv("test_prop");
Assert.assertEquals(s, "test_value2");
}
}
This solution gives the highest freedom: you can play with exactly the concerned variable exactly where required, although may suffer of code duplication it could also enforce tests isolation.
Run its main method before any executed JUnit test
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>process-test-classes</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.sample.EnvHack</mainClass>
<classpathScope>test</classpathScope>
</configuration>
</execution>
</executions>
</plugin>
Note what we are doing in this case:
We are invoking the java goal of the Exec Maven Plugin to actually invoke the mainClass of our env hack class.
We are invoking it with classPathScope set to test in order to make it visible to the Enforcer Plugin
We are running it as part of the process-test-classes phase just to make sure it is executed before the test phase and hence before any test.
This solution centralizes the whole prepare environment procedure, once for all tests.
On the other side, you may also consider to use mocking in your tests. This is not a centralized option (unless you code it) but could give further hints and hence worth to mention. Here is a sample code resetting an environment variable via PowerMock
package com.sample;
import org.junit.*;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(System.class)
public class EnvTest {
#Before
public void init() {
PowerMockito.mockStatic(System.class);
Mockito.when(System.getenv("TEST_PROP")).thenReturn("TEST_VALUE");
}
#Test
public void test() {
String var = System.getenv("TEST_PROP");
Assert.assertEquals("TEST_VALUE", var);
}
}
This is similar to the first and second approach proposed above.
Note that to make it work you need to add the following dependencies to your POM:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
</dependencies>
General note: indeed having tests which are not fully isolated and depends on the existence (or the absence) of an environment variable is not advisable. You may run into maintenance issues or have more nasty troubleshooting, for colleagues or for your future yourself. So, if you really need it, better to properly document it.

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

NoClassDefFoundError for MockitoInvocationHandler class

I am using mockito-all-1.9.5-rc1.jar and powermock-mockito-1.4.12-full.jar.
When I run this simple unit test for mocking final method in non-final class.
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ABC.class)
public class ABCTest {
#Test
public void finalCouldBeMock() {
final ABC abc = PowerMockito.mock(ABC.class);
PowerMockito.when(abc.myMethod()).thenReturn("toto");
assertEquals("toto", abc.myMethod());
}
}
When I ran it, I got
java.lang.NoClassDefFoundError: org/mockito/internal/MockitoInvocationHandler
Caused by: java.lang.ClassNotFoundException: org.mockito.internal.MockitoInvocationHandler
When I search fo class MockitoInvocationHandler in mockito-all-1.9.5-rc1.jar and powermock-mockito-1.4.12-full.jar. I couldn't find any.
Need help with this issue! Thank you
Mockito 1.9.5-rc1 had to be refactored internally to allow third party mock maker. MockitoInvocationHandler was part of the Mockito's internals (as the package name suggests) up to Mockito 1.9.0.
Due to these changes, current some older version Powermock releases as of today are not compatible with the latest Mockito release.
Another reason to avoid mocking/stubbing finals or statics ;)
Hope that helps
Cheers,

Categories

Resources