I've built an API using Spring Boot and have a few unit tests associated with it so far. As expected these are ran locally and when Jenkins builds the project via gradle build on the build server. I'm looking to add some integration tests to the project now using rest-assured so I can actually test request and responses but I'm not overly clear how to add them to the project.
So far I've added an integrationTests folder to src/test and have told gradle to exclude the rest-assured tests when gradle build or via gradle test so I can keep them independent. I've setup a gradle task gradle integrationTest to trigger the integration tests which runs fine as long as the API is currently running.
Apparently I can annotate the test class with #SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) to instruct spring to start up an embedded server for testing automatically but it doesn't appear to be doing anything, the tests just fail with a java.net.ConnectException error until I start the API in another window. Is there anything wrong with the below sample code or am I missing something else?
com.example.restassured;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static io.restassured.RestAssured.*;
#SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class RunSomeTestsIT {
#Test public void url_should_return_200_response() {
get("/v1/test/123456").then().statusCode(200);
}
}
build.gradle
task integrationTest(type: Test) {
include 'com/example/restassured/**'
// Run all tests each time. Do not cache.
outputs.upToDateWhen { false }
}
By co-incidence I was working on something very similar today, and hopefully can provide some useful pointers.
When I compare with this code I think you are missing the #RunWith(SpringRunner.class) annotation !
Edit: other than moving your test to the same package as the "Application" class, you can try a Spring "first-principles" approach which side-steps all the black-magic of the Spring annotations. At least you can troubleshoot things better and control what's going on:
https://github.com/ptrthomas/spring-testing/blob/master/src/test/java/example/HelloE2ERestKarateTest.java
Related
I want to Test my Endpoints using Karate, but when starting the Test I get following Error:
java.lang.IllegalArgumentException: Could not find option with name engine.WarnInterpreterOnly.
Java version: 11
Karate Maven Dependency:
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit5</artifactId>
<version>1.2.0.RC4</version>
</dependency>
Feature File:
Feature: To test the config-resource
Background:
* url baseUrl
Scenario: Add a new room
Given path 'addRoom/testRoom'
When method POST
Then status 201
Java Test class:
package at.htl.mqtt.client.boundary;
import com.intuit.karate.junit5.Karate;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
public class ConfigEndpointTest {
#Karate.Test
Karate testGetRoom() {
return Karate.run("config-resource.feature").relativeTo(getClass());
}
}
I have src/test/java as my testResource
Edit:
So I used the Runner API like you said but I still get the same Error.
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
#QuarkusTest
public class ConfigEndpointTest {
#Test
void testRoom() {
Results results = Runner.path("config-resource.feature").relativeTo(getClass()).parallel(5);
assertEquals(0,results.getFailCount(), results.getErrorMessages());
}
}
Btw I changed Java version to 16.
Any other suggestions?
I have a feeling the #Karate.Test annotation does not "play well" with the #QuarkusTest one.
So I recommend using the Runner API. You can find an explanation here: https://stackoverflow.com/a/65578167/143475
I am not sure if you still need a method annotated with #Test etc, please follow the Quarkus instructions that are appropriate.
I'm not sure about this specific Exception. I got this one
superclass access check failed: class com.oracle.truffle.polyglot.PolyglotImpl (in unnamed module #0x40729f01) cannot access class org.graalvm.polyglot.impl.AbstractPolyglotImpl (in module org.graalvm.sdk) because module org.graalvm.sdk does not export org.graalvm.polyglot.impl to unnamed module #0x40729f01
java.lang.IllegalAccessError: superclass access check failed: class com.oracle.truffle.polyglot.PolyglotImpl (in unnamed module #0x40729f01) cannot access class org.graalvm.polyglot.impl.AbstractPolyglotImpl (in module org.graalvm.sdk) because module org.graalvm.sdk does not export org.graalvm.polyglot.impl to unnamed module #0x40729f01
But what worked for me was to use #QuarkusIntegrationTest instead of #QuarkusTest. Also for whatever reason my tests would only run on GraalVM (I tried Azul, OpenJDK and Temurin neither of which worked). These are on Java 17
As far as I know #QuarkusIntegrationTest runs the application in an isolated process (even going as far as running the docker image created with quarkus.container-image.build is true) as opposed to #QuarkusTest which doesn't as a result letting us modify the context, inject mocks etc. When using #QuarkusIntegrationTest the application is only accessible via network calls.
There's also some caveats when it comes to running both of these tests in a single execution according to this.
I am trying to run all tests with the annotation #FastTests in a module using IntelliJ . I can run all tests in the module using the JUnit configuration with the test kind All In Package and the relevant package name.
When I try to run a single category by choosing the Category test kind JUnit configuration and choose Search For Tests: Across Module Dependencies or Search for Tests: In Single module I get No Tests were found
Is there a way to run JUnit tests with annotated with a single category in intellij?
Cheers
This works for me using Intellij IDEA 2018.1:
with category marker defined as interface:
public interface FastTests { /* category marker */ }
and test class or method annotated like this:
import cu.nicolau.sircap.nomencladores.FastTests;
import org.junit.Test;
import org.junit.experimental.categories.Category;
public class NomencladorServiceImplTest {
#Test
#Category(FastTests.class)
public void categoryTest() {
...
}
}
With JUnit 5, the #Category annotation gets replaced with the more flexible #Tag annotation.
If you consider migrating to JUnit 5, this blog can be a good place to start. Also, this and this answer can show you how to filter the tests execution based on their tags, using Intellij IDEA or Maven.
I am running some tests on an Android phone using gradle. However I would like to be able to select which tests to run. For the tests I am using jUnit4 and categories.
This is how the tests are build and executed from jenkins:
call gradle assembleDebug assembleDebugAndroidTest
call gradle connectedDebugAndroidTest
This is how a test looks like:
#Category(IncludeTest.class)
#Test
public void test_Test_06() throws Exception {
TestData.setUpTest("test_Test_06");
Log.d("Test: Test 6 included");
}
#Category(ExcludeTest.class)
#Test
public void test_Test_07() throws Exception {
TestData.setUpTest("test_Test_07");
Log.d("Test: Test 7 excluded");
}
In my gradle.build I have tried the following without success:
test {
useJUnit {
includeCategories 'com.abc.def.IncludeTest'
excludeCategories 'com.abc.def.ExcludeTest'
}
}
My structure is as follows:
/someFolder/gradle.build
/someFolder/app/src/android/java/
In java i have a package named com.abc and in that package there is another package, def where my IncludeTest and ExcludeTest interfaces are.
I have tried different paths to Include/ExludeTest in gradle.build but it just does not work, all test all always executed.
I have also tried putting the includeCategories/excludeCategories in a task and made sure the task was actually started. But still all test were executed. Just seems like includeCategories/excludeCategories does not do anything.
Is there anything basic I am doing wrong? Are there any other ways of selecting categories?
After some more research I found out that the includeCategories/excludeCategories does not work with Android.
I found a different solution when using AndroidJUnitRunner. In Gradle it is possible to filter tests on annotations. To include annotations:
call gradle connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation=com.abc.def.IncludeTest
There is also the possibility to exclude annotations using notAnnotation instead.
And of course there is syntax if you want to use multiple annotations with OR/AND combinations.
The following is also possible if you are not using connectedDebugAndroidTest:
adb shell am instrument -w -e annotation com.android.foo.MyAnnotation com.android.foo/android.support.test.runner.AndroidJUnitRunner
Some documentation: https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
I have some JUnit tests that contained in a .jar that is intended to be used as a library. The library contains some tests that should be run whenever the library is used in another project.
However when I create a new project using the library and run JUnit on it in Eclipse then the tests in the dependency .jar don't run / don't get detected by the JUnit test runner. I get the message:
No tests found with test runner 'JUnit 4'.
Is there a way I can configure the dependency .jar so that the tests will run alongside any tests that might be contained in the main project?
Basically I want the dependency .jar to "export" the tests to whatever projects it is used in.
I'm using Eclipse Juno, JUnit 4.10, and Maven for the dependency management.
EDIT:
The point of this library is to be able to help test projects that use it - i.e. it runs some specialised tests. This is why I want to be able to import the library .jar and have it contribute the extra tests to the importing project.
You can try Maven Surefire.
In some cases it would be useful to have a set of tests that run with various dependency configurations. One way to accomplish this would be to have a single project that contains the unit tests and generates a test jar. Several test configuration projects could then consume the unit tests and run them with different dependency sets. The problem is that there is no easy way to run tests in a dependency jar. The Surefire plugin should have a configuration to allow me to run all or a set of unit tests contained in a dependency jar.
This can be done as follows (Junit 3):
Ensure test jar contains a class which has a static suite() method
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite()
{
TestSuite suite = new TestSuite( "All Tests");
suite.addTestSuite(TestOne.class);
suite.addTestSuite(TestTwo.class);
return suite;
}
}
Then in the project using the test-jar dependency:
create a TestCase:
package org.melati.example.contacts;
import org.melati.poem.AllExportedTests;
import junit.framework.Test;
import junit.framework.TestCase;
public class PoemTest extends TestCase {
public static Test suite()
{
return AllExportedTests.suite();
}
}
Now the tests will be found.
I think that making a library of unit tests (#Test annotated methods) is a bad idea. However, making a library of reusable test components is a good one. We've done this in a few open source projects, and you can take a look how it works.
One Maven module exports test components (we call them "mocks"), from src/mock/java directory. Exported artifact has -mock classifier. See rexsl/pom.xml (pay attention to highlighted lines).
Mock artifacts are being deployed to Maven Central, together with usual artifacts: http://repo1.maven.org/maven2/com/rexsl/rexsl-core/0.3.8/ (pay attention to ...-mock.jar files)
Modules that need that mocks can include them as usual artifacts, for example rexsl-core/pom.xml (see highlighted lines):
Then, in your unit tests just use the classes from that mock libraries, like regular builders of mocks, for example: BulkHttpFeederTest
That's how you can make your test artifacts reusable, in an elegant way. Hope it helps.
#Mikera,
I find that this may help you. Just extend the Testcase Class to one of your java classes in project and you can run that particular class to run it as a JUnit Test.
I am not sure that this is desirable - On the one hand, if you use a jar, its behaviour might be influenced by the external context, e.g. other libraries in the classpath. From inside the jar, there is no simple way to analyse this context and to adjust the tests accordingly. On the other hand, if you write and compile a library, you should test it before packaging it as a jar. You might even want to not include your tests.
If it is really important to you to run the tests again, I would be interested in what could make them fail without changing the jar. In that case, however, you might want to extend the testrunner. As far as I know it uses reflection. You can quite easily load jars in a classloader and go through all their classes. By reflection you can identify the test classes and assemble testsuites. You could look into the testrunner for an example. Still, you would need to start this process from outside, e.g. from inside one of your test classes in the client project. Here, QATest's approach might be helpful: By providing an overriden version of testsuite or testrunner, you could automate this - if the client uses your overridden API.
Let me know if this rather costly approach seems to be applicable in your scenario and I can provide code examples.
Why should the user of the jar run the test cases inside the jar!!! When the jar is packaged and delivered, it means that the unit tests are run successfully.
Typically, the jar itself should be either treated as a separate project or as one of the modules. In both the cases, unit test cases are run before its delivered.
I want to be able to run all tests in a project programmatically. I know Eclipse has a "Run as JUnit test" configuration which somehow grabs all the tests in a project and run them. Is there any way for me to also grab the list of tests programmatically and run them? Or is there some good way to construct a test suite containing all the test cases without manually listing out every one (all 700+) of them?
I've tried the "New... -> Test Suite" option in Eclipse, but that seems to work only for JUnit 3, identifying tests by their extending from TestCase
The test classes are JUnit 4, so their only distinguishing characteristic is the annotation, no naming convention, no subclassing from TestCase.
Thanks in advance!
Though it does not really solve your immediate problem, I find it a very useful general practice to create suites and suites of suites, e.g. for a package something like PackageFooSuite etc. and assemble these suites in one or more suites again, like ModuleFooSuite and have one top-level suite, like AllTestsSuite. That way it's easy to run both all tests in one step as well as submodule tests for the package I'm currently working on (and have the tests run quicker than if I would always run all of them):
#RunWith(Suite.class)
#Suite.SuiteClasses({ PackageFooSuite.class, PackageBarSuite.class} )
public final class AllTestsSuite {} // or ModuleFooSuite, and that in AllTests
None of the other answers did it for me. I had 40k tests I needed to run, so manually listing every class was not an option.
I did it with ClasspathSuite. A test suite that runs all Junit4 and Junit3 test cases in the class path is as follows:
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.*;
import org.junit.runner.RunWith;
import org.junit.runner.JUnitCore;
import static org.junit.extensions.cpsuite.SuiteType.*;
#RunWith(ClasspathSuite.class)
#SuiteTypes({ JUNIT38_TEST_CLASSES, TEST_CLASSES })
public class RunAllSuite {
/* main method not needed, but I use it to run the tests */
public static void main(String args[]) {
JUnitCore.runClasses(RunAllSuite.class);
}
}
I needed to run it from command line, so this is what I did:
Downloaded cp-1.2.6.jar
Create the previously mentioned RunAllSuite
Compile the class, javac RunAllSuite.java -cp cpsuite-1.2.6.jar;junit-4.8.1.jar
run it with target tests in the class path, java -cp cpsuite-1.2.6.jar;junit-4.8.1.jar;path/to/runallsuite/folder;target/classes;target/test-classes RunAllSuite
And that's it. With the RunAllSuite above, anywhere in your code you can just do JUnitCore.runClasses(RunAllSuite.class), which runs all tests in class path. There are other config options as well which are explained in the ClasspathSuite home page.
Note also that the class given above does not print anything. If that is needed, you can do
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.*;
import org.junit.runner.RunWith;
import org.junit.runner.JUnitCore;
import org.junit.internal.TextListener;
import static org.junit.extensions.cpsuite.SuiteType.*;
#RunWith(ClasspathSuite.class)
#SuiteTypes({ JUNIT38_TEST_CLASSES, TEST_CLASSES })
public class RunAllSuite {
public static void main(String args[]) {
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(RunAllSuite.class);
}
}
You can do this fairly easily from within maven using the surefire plugin: I usually clean/compile/install my projects from the command line before comparing them for eclipse usage (mvn eclipse:clean eclipse:eclipse) and you can define a test suite in your pom which lists all the tests you want to run en masse every time you run mvn install. You're not calling them programatically, exactly, but you can certainly call them en masse.
In Eclipse (I'm using 4.6.1) - Right click the project folder, select "Run As", choose "JUnit Test"
It will run all tests in that project. Same for a package.
Of the top of my head using Spring:
Implement a TypeFilter that matches classes with methods annotated with #Test (don't forget to consider the superclasses)
Invoke classpath scanning on your top-most test package
Invoke the JUnitRunner with the scan results
More info on classpath scanning and custom type filters here
With Eclipse Indigo (possibly Helios as well) in the Run Configurations dialog box, you now have the ability to Run all tests in a selected project, package or source folder.
Also a good reference from Eclipse is the article Java Unit testing with JUnit 4.x in Eclipse.
I also recommend using the JUnit Suite annotations. Follow the link for more detail.