-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Closed
Milestone
Description
@TestInstance annotation seems to cause threading problems with tests in Spring Boot.
<junit5.jupiter.version>5.3.0-M1</junit5.jupiter.version>
<junit5.platform.version>1.2.0</junit5.platform.version>I was able to replicate this problem by creating a small Spring Boot application using the Spring Initializer (https://start.spring.io/).
The application:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}A dummy class for testing:
package com.example.demo;
public class Klass {
public Klass(String field) {
this.field = field;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
String field;
}My test class:
package com.example.demo;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
// @TestInstance(TestInstance.Lifecycle.PER_CLASS) // Needed for BeforeAll annotation but causes threading issues.
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {DemoApplication.class})
public class DemoApplicationTests {
@Test
public void contextLoads() {
}
Klass klass = null;
@BeforeEach
public void beforeEach() {
klass = new Klass(Thread.currentThread().getName());
}
@RepeatedTest(8)
public void parallel() {
klass.setField("Modified: " + klass.getField());
}
@AfterEach
public void afterEach() {
System.out.println(String.format("%s - %s", Thread.currentThread().getName(), klass.field ));
}
}Output when not using @TestInstance:
ForkJoinPool-1-worker-3 - Modified: ForkJoinPool-1-worker-3
ForkJoinPool-1-worker-0 - Modified: ForkJoinPool-1-worker-0
ForkJoinPool-1-worker-2 - Modified: ForkJoinPool-1-worker-2
ForkJoinPool-1-worker-3 - Modified: ForkJoinPool-1-worker-3
ForkJoinPool-1-worker-4 - Modified: ForkJoinPool-1-worker-4
ForkJoinPool-1-worker-4 - Modified: ForkJoinPool-1-worker-4
ForkJoinPool-1-worker-6 - Modified: ForkJoinPool-1-worker-6
ForkJoinPool-1-worker-2 - Modified: ForkJoinPool-1-worker-2
Output when using @TestInstance:
ForkJoinPool-1-worker-0 - Modified: ForkJoinPool-1-worker-4 <<< oops
ForkJoinPool-1-worker-2 - Modified: ForkJoinPool-1-worker-4 <<<
ForkJoinPool-1-worker-3 - Modified: ForkJoinPool-1-worker-3
ForkJoinPool-1-worker-0 - Modified: ForkJoinPool-1-worker-0
ForkJoinPool-1-worker-4 - Modified: ForkJoinPool-1-worker-0 <<<
ForkJoinPool-1-worker-2 - Modified: ForkJoinPool-1-worker-2
ForkJoinPool-1-worker-3 - Modified: ForkJoinPool-1-worker-3