I'm trying to run an integration test using kotest and running in to the below error. The tests run fine if I only run a single test but it fails when I try to run all tests in the class.
Failed to find merged annotation for #org.springframework.test.context.BootstrapWith(org.springframework.boot.test.context.SpringBootTestContextBootstrapper.class)
java.lang.IllegalStateException: Failed to find merged annotation for #org.springframework.test.context.BootstrapWith(org.springframework.boot.test.context.SpringBootTestContextBootstrapper.class)
HelloTest.kt
#SpringBootTest(classes = [DemoApplication::class])
class HelloTest: FunSpec() {
override fun extensions() = listOf(SpringExtension)
init{
test("should..."){
...
}
test("should..."){
...
}
}
}
Related
My environment is Spring Boot 3.0.2, Gradle and Java 17. I implemented an application with more than 300 unit and integration tests.
After 200 tests my suite became unstable. If I launch the tests from intellij they all work correctly. If I run the tests one by one from the gradle command they also work fine. But if I run all the tests together, some randomly fail.
The error is that it fails to load certain mockbeans.
If I put this configuration in the build.gradle then all the tests go well, but it takes a long time.
tasks.named('test') {
forkEvery = 1
useJUnitPlatform()
}
If I put this other configuration, then other tests fail
tasks.named('test') {
maxParallelForks = Runtime.runtime.availableProcessors()
useJUnitPlatform()
}
Could it be a memory problem? parallel processes or something similar? It is very strange, the truth that does not give me any confidence.
For example, a test class.
package ...
import ...
#SpringBootTest
#ActiveProfiles("test")
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
class OfferCreateTest {
#Autowired
PropertyCreate propertyCreate;
#Autowired
OfferCreate offerCreate;
#MockBean
ObHttpClient obHttpClient;
#MockBean
RoomtypeFind roomtypeFind;
#MockBean
RateplanFind rateplanFind;
#MockBean
PropertyChannelFind propertyChannelFind;
private Long propertyId;
#BeforeAll
void setup(){
propertyId = createProperty();
}
private Long createProperty(){
PropertyCreateDto propertyCreateDto = PropertyCreateDtoMother.randomWithFullData();
return propertyCreate.create(propertyCreateDto).getResult().get("id");
}
#Test
void create_offer(){
OfferCreateDto offerCreateDto = OfferCreateDtoMother.random();
Long offerId = offerCreate.create(propertyId, offerCreateDto).getResult().get("id");
assertTrue(offerId >= 100000L);
}
#Test
void create_offer_on_non_existing_property(){
OfferCreateDto offerCreateDto = OfferCreateDtoMother.random();
assertThrows(Exception.class, () -> offerCreate.create(ContentGenerator.customIdLower(), offerCreateDto));
}
}
Very thanks,
I am writing a Grails-5 and I am using cucumber for BDD. I've followed the tutorial at: https://www.baeldung.com/java-cucumber-gradle
I can run my unit tests using:
$ ./gradlew check
And I can run my cucumber BDD tests by starting the server in one shell:
$ ./gradlew server:bootRun
And invoking the tests in another:
$ ./gradlew cucumberCli
Is it possible to configure build.gradle in such a way as to have ./gradlew check run the unit tests, then start the server, then run the cucumber tests, and finally bring the server back down?
If at all possible, it would be even better if the cucumber infrastructure could start and stop the server between each test. That way each test would start in a known state.
I managed to get this working by adding #Before and #After steps to my StepDefinitions.groovy file:
def serverProcess
private String getBaseUrl() {
return "http://localhost/"
}
#Before
public void startServer() {
try {
serverProcess=Runtime.getRuntime().exec("../gradlew bootRun")
} catch (IOException e) {
e.printStackTrace()
}
def done = false
while(!done) {
try {
done = new URL(getBaseUrl()).openConnection().getResponseCode() == 200
} catch(Exception e) {
Thread.sleep(500)
}
}
}
#After
public void stopServer() {
serverProcess.destroy()
}
I am trying to capture screenshots in my extent report by using JUnit Maven.
I am able to generate the reports but ITestResult is not working in JUnit Maven in #After. I would highly appreciate if somebody can help in the code replacement from TestNG to Junit. Please find attached my code.
#After public void tearDown(ITestResult result) throws IOException {
if(result.getStatus()==ITestResult.FAILURE){
String temp = Utility.getScreenshot(driver);
logger.fail(result.getThrowable().getMessage(), MediaEntityBuilder.createScreenCaptureFromPath(temp).build());
}
I assume you are using JUnit 5.
You will have to implement your own test execution listener based on the interface TestExecutionListener.
The following method will be called after any test execution:
default void executionFinished​(TestIdentifier testIdentifier,
TestExecutionResult testExecutionResult){
if(testExecutionResult.getStatus() == TestExecutionResult.Status.FAILED){
// your code here
}
}
In the gradle script below, maxParallelForks and forkEvery will start a new process with a new JVM per Junit test class. Is there a way to give each test process/JVM/Junit class its own unique system property?
I tried an experiment where I passed a UUID value as a system property in the beforeSuite method.
apply plugin:'java'
test {
ignoreFailures = true
maxParallelForks = 8
forkEvery = 1
systemProperty 'some.prop', 'value'
beforeSuite { descriptor ->
logger.lifecycle("Before suite: " + descriptor)
def theuuid = UUID.randomUUID().toString()
println "beforeSuite uuid =" + theuuid
systemProperty 'some.uuid', theuuid
}
beforeTest { descriptor ->
logger.lifecycle("Running test: " + descriptor)
}
}
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
The JUnit test classes, LoginTest1 and LoginTest2 print out the system property in a test method.
public class LoginTest1 {
private String userName="Gradle";
#Test
public void testUserName() throws Exception {
System.out.println("LoginTest1: Testing Login ");
System.out.println("LoginTest1: Testing Login some.prop -> "
+ System.getProperty("some.prop"));
System.out.println("LoginTest1: Testing Login some.uuid -> "
+ System.getProperty("some.uuid"));
assertTrue(userName.equals("Gradle"));
}
}
public class LoginTest2 {
private String userName="Gradle";
#Test
public void testUserName() throws Exception {
System.out.println("LoginTest2: Testing Login ");
System.out.println("LoginTest2: Testing Login some.prop -> "
+ System.getProperty("some.prop"));
System.out.println("LoginTest2: Testing Login some.uuid -> "
+ System.getProperty("some.uuid"));
assertTrue(userName.equals("Gradle"));
}
}
As you can see from the gradle output below, the beforeSuite method is called before running individual JUnit test methods. Both test classes get the same system property of 6a006689-474f-47d5-9649-a88c92b45095
$ gradle clean test
> Task :test
Before suite: Gradle Test Run :test
beforeSuite uuid =6a006689-474f-47d5-9649-a88c92b45095
Before suite: Gradle Test Executor 1
beforeSuite uuid =39edb608-3027-4ad8-bd15-f52f50175582
Before suite: Test class ch6.login.LoginTest1
beforeSuite uuid =c0ce55e0-924c-4319-becb-bc27229c9cf3
Before suite: Gradle Test Executor 2
beforeSuite uuid =c15eaac0-7ea7-46d2-8235-8dc49b3f7a39
Running test: Test testUserNameNotNull(ch6.login.LoginTest1)
Before suite: Test class ch6.login.LoginTest2
beforeSuite uuid =73abbe24-5b78-4935-867a-445ac4ac20ef
Running test: Test testUserName(ch6.login.LoginTest1)
Running test: Test testUserName(ch6.login.LoginTest2)
JUnit test class output:
LoginTest1: Testing Login
LoginTest1: Testing Login some.prop -> value
LoginTest1: Testing Login some.uuid -> 6a006689-474f-47d5-9649-a88c92b45095
LoginTest2: Testing Login
LoginTest2: Testing Login some.prop -> value
LoginTest2: Testing Login some.uuid -> 6a006689-474f-47d5-9649-a88c92b45095
It looks like there's an initial call to beforeSuite (seen as ":test") and then once per Test Executor. The first uuid value ("6a006689") is set across all JVMs. Is there anything like a simple beforeClass method I could use?
In the debug log below,it looks like the Test Executors are given the jvm argument -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 and that is used soley to create new JVMs (as per the forkEvery config). This makes me think that what I want to do is impossible in Gradle.
20:23:42.466 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'Gradle Test Executor 1'. Working directory: /a/b/ Command: /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Dorg.g
radle.native=false -Dsome.prop=value -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea -cp /data/.gradle/caches/4.3.1/workerMain/gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 1'
20:23:42.466 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'Gradle Test Executor 2'. Working directory: /a/b/ Command: /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Dorg.g
radle.native=false -Dsome.prop=value -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea -cp /data/.gradle/caches/4.3.1/workerMain/gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 2'
Update 8/2018
The following solution does not work in Gradle 4.9 and greater
Instead, there is a org.gradle.test.worker system property which you can use to distinguish between workers, calculate display names, temporary directories, etc. This test.worker is simply an increasing long value. The Gradle team has no plans on making Test Workers configurable. A pity because I had to do some major refactoring in my test code in order to upgrade Gradle. The "#BeforeAllCallback" in JUnit 5 might be useful to you.
Trying to solve by intercepting Test.copyTo(JavaForkOptions target)
This code demonstrates lance-java 's suggestion and succeeds in answering my question. I have the following build.gradle script which uses MyTestTask to extend Test and add a unique value called my_uuid. Note that the build script must have forkEvery = 1 to ensure copyTo is called once per JUnit test:
class MyTestTask extends Test {
public Test copyTo(JavaForkOptions target) {
super.copyTo(target);
String uuid = UUID.randomUUID().toString();
System.out.println("MyTestTask copyTo:\n my_uuid=" + uuid);
System.out.println("\t before getJvmArgs:" + target.getJvmArgs());
System.out.println("\t before getSystemProperties:" + target.getSystemProperties());
target.systemProperty("my_uuid", uuid);
System.out.println("\t after getJvmArgs:" + target.getJvmArgs());
System.out.println("\t after getSystemProperties:" + target.getSystemProperties());
return this;
}
}
///
subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
test {
enabled false // This doesn't seem to matter.
}
task my_test(type: MyTestTask) {
forkEvery 1 // need this so copyTo called each JUnit test
testLogging.showStandardStreams = true
doFirst {
def uuid = UUID.randomUUID().toString()
println "TEST:Task name is $name. In doFirst. uuid is " + uuid
jvmArgs '-Dcommon_uuid='+ uuid
}
}
}
The Junit tests that are executed are trivial and simply print out System.getProperty("my_uuid") and System.getProperty("common_uuid").
> Task :CustomCopyToSubProject:my_test
TEST:Task name is my_test. In doFirst. uuid is eed1ee92-7805-4b8e-a74c-96218d1be6e1
MyTestTask copyTo:
MyTestTask copyTo:
my_uuid=a7996c20-1085-4397-9e32-fd84467dcb45
my_uuid=69f6f347-71d0-4e5d-9fad-66bf4468fab3
before getJvmArgs:[]
before getJvmArgs:[]
before getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1]
before getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1]
after getJvmArgs:[]
after getJvmArgs:[]
after getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1, my_uuid:69f6f347-71d0-4e5d-9fad-66bf4468fab3]
after getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1, my_uuid:a7996c20-1085-4397-9e32-fd84467dcb45]
ch3.LoginTest2 > testUserName2 STANDARD_OUT
LoginTest2.java: Testing Login ! >>---> my_uuid=a7996c20-1085-4397-9e32-fd84467dcb45 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1
ch3.LoginTest1 > testUserName1 STANDARD_OUT
LoginTest1.java: Testing Login ! >>---> my_uuid=69f6f347-71d0-4e5d-9fad-66bf4468fab3 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1
The task my_test sets common_uuid in doFirst. The MyTestTask.copyTo method sets its own my_uuid.
You can see from the output and MyTestTask is called twice, once per JUnit test task (LoginTest1 and LoginTest2). The two JUnit tests get their own unique system property in my_uuid.
I think you want to intercept Test.copyTo(JavaForkOptions target), unfortunately the only way I can see to do this is to extend Test
eg
public class Test2 extends org.gradle.api.tasks.testing.Test {
public Test copyTo(JavaForkOptions target) {
super.copyTo(target);
target.systemProperty("uuid", UUID.randomUUID().toString());
return this;
}
}
build.gradle
apply plugin: 'java'
test {
enabled = false
}
task test2(type: Test2) {
// guessing you'll need to configure a bit of stuff here
}
check.dependsOn test2
Since a new JVM is forked for every test you could just use a static field that is initialized with a UUID.
public class Helper {
public static final String uuid = UUID.randomUUID().toString();
}
public class LoginTest2 {
private String userName="Gradle";
#Test
public void testUserName() throws Exception {
System.out.println("LoginTest2: Testing Login ");
System.out.println("LoginTest2: Testing Login some.uuid -> "
+ Helper.uuid;
assertTrue(userName.equals("Gradle"));
}
}
I have a gradle project that brings in Jersey 2.13, does testing through TestNG, and leverages the Jersey Test Framework. Any test I run as a plain-jane Unit Test through the #Test annotation runs fine. If I try to put the Jersey Tests into a TestNG group via #Test(groups = {"integration"}), the tests fail with a NPE coming from org.glassfish.jersey.test.JerseyTest. Tests NOT leveraging the Jersey Test framework don't have this problem correctly executing as part of #Test(groups = {"integration"}). Any ideas why TestNG can't get this container properly started when under groups constraints?
Here is the operative parts of the project...
build.gradle
dependencies {
...
compile 'org.glassfish.jersey.core:jersey-server:2.13'
compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.13'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.13'
...
testCompile 'org.testng:testng:6.8.8'
testCompile 'org.glassfish.jersey.test-framework:jersey-test-framework-core:2.13'
testCompile 'org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-jetty:2.13'
}
test {
useTestNG() { excludeGroups 'integration' }
}
task integrationTest(type: Test, dependsOn: 'test') {
useTestNG() { includeGroups 'integration' }
}
The failing integration tests...
public class JerseyTestNGTest extends JerseyTestNg.ContainerPerClassTest {
#Path("hello")
public static class HelloResource {
#GET
public String getHello() { return "Hello World!"; }
}
#Override
protected Application configure() {
return new ResourceConfig(HelloResource.class);
}
#Test
public void notIntegrationTest() {
// works like a champ...
doIt();
}
#Test(groups = {"integration"})
public void integrationTest() {
// NPEs out the wazoo
doIt();
}
private void doIt() {
final String hello = target("hello").request().get(String.class);
assertEquals("Hello World!", hello);
}
}
The trail of tears...
$ gradle integrationTest
...
:integrationTest
Gradle test > jerseywtf.JerseyTestNGTest.integrationTest FAILED
java.lang.NullPointerException at JerseyTestNGTest.java:29
2 tests completed, 1 failed
:integrationTest FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':integrationTest'.
> There were failing tests. See the report at: file:///Users/robert.kuhar/work/jerseywtf/build/reports/tests/index.html
...
BUILD FAILED
The actual stacktrace...
java.lang.NullPointerException
at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:566)
at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:580)
at jerseywtf.JerseyTestNGTest.doIt(JerseyTestNGTest.java:29)
at jerseywtf.JerseyTestNGTest.integrationTest(JerseyTestNGTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
What's up with that?
The whole project is on github, if you're at all interested in seeing it run, or fail as the case may be: https://github.com/robertkuhar/JerseyWTF