Why classes loaded with boot classloader (bootclasspath) doesn't include annotations - java

I was writing unit tests for my javaagent but faced with behavior of JVM I guess which I wasn't aware before and I curious if there is any explanation or article about it. I tried google it and search on SO but with no success.
I found that classes which are included into boot classpath doesn't have annotations with them. To demonstrate it I created a simple JUnit test
import org.junit.Test;
public class SimpleTest {
#Test
public void myTest() {
}
}
It perfectly runs of course :) but if I configure eclipse project like this:
Then it fails with java.lang.Exception: No runnable methods. I see in the debugger that code which checks annotations cannot find them.

I found answer on SO to my question which is perfectly explains what is going on (I voted up there).
https://stackoverflow.com/a/23502439/2013497
JUnit library is added by Eclipse and it goes to regular classpath whenever bootloaded classes doesn't have a way to reference them.

Related

How to detect a nested Unit Test classes (not under test folder) in Java

I know that it's quite hard to test many features of Java language. For example, it would be impossible to test a private variables of a class or similar methods.
I generally tackle this by making a nested class, where this nested class is a unit test, such that :
public class MyClass{
private String somePrivate;
// omitted for brevity
#RunWith(MockitoJUnitRunner.class)
public static class MyClassUnitTest{
#InjectMockito
MyClass myclassMocked;
// so forth...
}
}
thus no need for reflection/powermock or others!
This structure helps me to test all unreachable members or methods of a class.
But it appears that i also should make an automated build where maven will look up this nested classes for unit tests and run it when i mvn clean test in the deployment.
I've been trying to find any answer on this but to no avail i couldn't find any spec of maven or maven-surefire-plugin to say that 'hey please look at these nested classes in the src/main folder and mark them as unit test'. Also, i am using springboot to package all of my project (thus most of the dependencies are with spring)
Anyone up for solution?
For example, it would be impossible to test a private variables of a class or similar methods
You don't need to do this - private methods are private, and they are indirectly tested by testing methods that use them.
You should not be embedding test code or libs such that they have to ship with production software, period.
Don't do what you are proposing.
Edit based on your comment:
As for how you would do it technically, Maven only supports 1 directory for test sources.
You could do something like create an integration test setup that would find the tests in your src/main directory, but the reason this is not easy to do with Maven is because Maven promotes sane patterns and your pattern is not one of those.
Howto add another test source folder to Maven and compile it to a separate folder?

Is there a way to reload application.yml before test class?

I'm trying to test a method with #SpringBootTest and #ActiveProfile("test") in my class. When I run the new tests, everything works fine and the properties are loaded from the test YML file correctly. But when I run all tests, those same tests load the properties from the production YML file.
I've tried using #DirtiesContext, with BEFORE_CLASS and BEFORE_EACH_METHOD flags, on the new test class but it doesn't seem to help.
I have something similar to the following:
#ActiveProfiles("test")
#SpringBootTest
public class NewTestClass{
...
#Test
public void testThatLoadsPropertiesAndShouldLoadApplicationTestYmlFile() {
...
}
}
What am I missing here? is there a simple way of solving this problem?
UPDATE
I disabled the other Integration Tests on the project using #Disable from Junit 5 and checked if the problem persisted. surprisingly, it did. So I'm suspecting it is not an ApplicationContext caching problem.
Having the problem description provided I can only suggest the that there might be another test suite configured so that the context is setup using the production config (yml). Please consult this answer (the question raised is similar in a way...): https://stackoverflow.com/a/43332643/8085853
Ok, I believe I found the cause of the problem. I'm running all tests using IntelliJ, but "all tests" is being managed by the JUnit plugin and the single tests are being managed by the Gradle plugin. Once I used gradle to run "all tests", everything worked.

JAssert library not incorporated in Spring Boot test

I am testing a Spring Boot application using code from a tutorial. The tutorial describes the setup and configuration of a Spring Boot application, and also describes a test that uses JAssert calls in the following manner:
package hello;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class SmokeTest {
#Autowired
private HomeController controller;
#Test
public void contexLoads() throws Exception {
assertThat(controller).isNotNull();
}
}
The test, unfortunately, will not compile in my IDE. The compilation is failing on the assertThat() method.
I am using Eclipse with Maven for my IDE. I have checked the Maven dependencies and see that the JAssert core library is included. Unfortunately, despite this the compiler can not seem to "find" the assertThat() call.
It fails to compile the test for that reason.
How do I get the test to utilize JAssert and find the calls to JAssert functions?
I'm not an eclipse expert, but it seems like you have some configuration issue here.
If you're sure that the dependency appears in pom.xml in scope test then try to eliminate eclipse related issues by running the tests directly via maven:
mvn test
will do the job
If it runs sucessfully, then re-create eclipse configurations from pom.xml / re-import the project.
If not, its a pom.xml related issue and has nothing to do with eclipse, you'll have to fix the pom or maven ecosystem. I suggest the following:
go to the local repository and remove the dependency from the file system (manually, the whole directory, with jar, pom.xml and everything) and then rerun mvn test
Sometimes dependencies are downloaded corrupted and despite being defined correctly in pom.xml they do not really contain classes in a form that java/maven can read
Actually:
It turns out that neither the Boot starter nor the IDE seems to find the necessary import declaration for the JAssert functions. Could it be because they are static?
In looking at some example code, I found in the code the import declaration for the assertThat() method. Usually, Eclipse would have suggested this declaration but it does not.
What is weird is that I put in the declaration by hand, and not only does this allow me to compile, but Eclipse, once the import is included, the code assistant makes proper assertThat() suggestions without problems!
There could be a bug somewhere, but that is beyond the scope of my particular problem. My test now compiles without problems.
I hope someone looking at this can figure out why Elipse's code assist does not work for this particular library properly. I wouldn't be surprised to discover that there are other objects/libraries in Spring Boot that don't get properly handled by the code assistant.

Using JUnit with Groovy classloader

I have a simple Groovy test class using JUnit
class GroovyJunitTest {
#Test
void test() {
println this.class.getClassLoader().toString()
}
}
This prints out
sun.misc.Launcher$AppClassLoader#4e25154f
which means that Java classloader is used.
I run the test with both Intellij IDE and using gradle test. The same result is in both cases.
Is there a way to configure JUnit to use Groovy classloader?
Once I had the same problem and I used https://github.com/bitstrings/junit-clptr
to load my custom classloader.
Note: this is no longer supported by the crator however for me it did work out. Anyway if it's to important to trust an outside source you can take it as an inspiration and define your own annotation that will let you choose your custom classloader

java.lang.Exception: No tests found matching Method using Intellij IDEA

I am experiencing a strange behavior of Intellij IDEA 2016.3. Having a class with method foo and a JUnit test for the method when I get java.lang.Exception: No tests found matching Method foo when running the test. After I do mvn test it succeeds and then running the unit test right after executing mvn command it suddenly runs green. Seems like IDEA does not compile automatically. How can I fix this?
P.S. No settings were altered after upgrading to v. 2016.3
If you're using a theory testing framework like Junit's or Robolectric's, make sure to run the class containing the test you want, instead the test itself. Since these frameworks use the test methods as instance methods instead of static methods, any testing framework looking for a normal public static test won't find anything.
The same issue i got with Gradle (4.5+) + new Build Cache feature
Sometimes it's unable to find new test methods and throws exception (like you mentioned in topic)
Solution: clean .gradle, build and out directories and try again ;)
Well, after "playing" a bit with run configurations of each unit test I noticed that each Run Config has a Build goal preset in the Before Launch option (See pic below):
After changing Build to Build Project the tests run fine.
If you originally run a test named "foo", and then rename it to "fooBar", you must subsequently run "fooBar" with a new Run Configuration.
If you use the same original Run Configuration for "foo" to run "fooBar", it still looks for a test named "foo" which it does not find (thus the Exception) because it was renamed to "fooBar". The new Run Configuration would correctly look for "fooBar" test.
I made this mistake unknowingly because I renamed a test, but then just clicked the green run button in IntelliJ: Doing that runs the last Run Configuration, which in this scenario has the old "foo" name.
Deleting Intellij's out directory fixed this issue for me.
In addition to the other answers here: the error can also happen when you forget #Test before your test method declaration. IntelliJ (2018.1) will still show you the green "Play-Button" for test execution, but that public method in your Test-Class will not be an actual test.
Make sure that your #test methods as well as the test class are public.
Since you got your answer and for others searching for solution,
Look if your test class is extending TestCase abstract class which is a JUnit 3 related. In order to fix this you have to start your method name with "test".
For example public void testFoo().
If JUnit 3 is not the case, you're missing #Test annotation from your JUnit 4 test method.
Note: If you're extending from TestCase and test methods are annotated with #Test and also your methods' names start with "test", then probably you're mixing JUnit 3 with JUnit 4. Don't do that. It will lead to other errors such as methods that annotated with #Ignore will not be ignored if those methods' names start with "test".
This situation can also occur if you do not place #Test annotation above the test method.
Maybe you just give a wrong name for test method.
I met this problem because I used '—' instead of '_' which intelliJ cannot represent.
I had to add test before the test Method Name.
methodtest() does not work but testMethod() worked
Make sure #org.junit.Test is added on top of your method. I forgot them and that fixed it for me!
Make sure you've correct runner mentioned above your class.
I was getting this weird message when I was using runner CucumberWithSerenity.class. When I changed to SerenityRunner.class it got fixed.
#RunWith(SerenityRunner.class)
//#RunWith(CucumberWithSerenity.class)
public class WordPressAppTest {
I'm using Serenity framework for web automation and use below runner class
import net.serenitybdd.cucumber.CucumberWithSerenity;
import net.serenitybdd.junit.runners.SerenityRunner;
import org.junit.runner.RunWith;
I feel IDEA ( 2017.2.6 ) can show some better error message than this
You may check that Run/Debug Configurations in the top of the IntelliJ screen.
Delete all of then with the "minus button" and hit "run" green button again to run the test.
You may reload the project on the maven tab on the right as well.
In my spring mvc project. I solved this problem by adding
#RunWith(SpringJUnit4ClassRunner.class)
to my test class.
In my case, I copied a test from another class and modified it, but while running the test it was still pointing to the previous one.
Build > Clean Project solved the problem

Categories

Resources