Search code examples
integration-testingspring-boot-testmockmvclogback-classic

@AutoConfigureMockMvc fails integration tests with inifnite loop


We had an integration tests such as the one that follows that used to work:

@ActiveProfiles("local")
@WithMockUser("j_unit_user_http_test")
@RunWith(SpringRunner.class)
@SpringBootTest(
    classes = { Application.class },
    webEnvironment = RANDOM_PORT
)
@Transactional
@Rollback
@AutoConfigureMockMvc()
public abstract class HttpTest {

    static {
        //reads and sets a dependency related props
        PropertiesReader propertiesReader = new PropertiesReader();
        propertiesReader.readDependencyProperties().forEach(System::setProperty);
    }

    @Autowired
    private MockMvc mockMvc;

    @PersistenceContext
    private EntityManager em;


    @Test
    public void createDashboard() {
        // POST is a utility method that wraps "mockMvc.perform(post(url))", I've omitted it here for brevity.
        var postResult = POST("/api/dashboards", Map.of("name", "wonderland"));
        var newDashboard = extractJson(postResult);
        assertTrue(newDashboard.get("id").isInt());
    }

}

Among the changes we made the significant ones that seem to be causing the errors are:

  1. Upgrading spring-boot from '2.3.0' to '2.5.6'
  2. Setting the environment properties needed by some of our dependencies in the static void main class of our app:
public class Application {

    public static void main(String[] args) {
        // reads and sets dependency related props
        PropertiesReader propertiesReader = new PropertiesReader();
        propertiesReader.readDependencyProperties().forEach(System::setProperty);
    }
}

The error we get is:

java.lang.StackOverflowError
    at java.base/java.lang.Throwable.getOurStackTrace(Throwable.java:828)
    at java.base/java.lang.Throwable.getStackTrace(Throwable.java:820)
    at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:55)
    at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:60) // several frames of this follow

My guess is that the mockMvc is not getting configured correctly, because if I use it without @SpringBootTest and @AutoConfigureMvc, the tests work. Any idea what could be wrong?


Solution

  • The above issue has been fixed.

    In the commit when the tests started failing, among other changes, the spring-boot version was changed from 2.3.x to 2.5.x Turns out in version 2.4 spring-boot removed JUnit 5's vintage engine.

    As pointed out in their release notes, ideally, i should migrate the tests to junit 5, but, in the meantime, adding the following in build.gradle helps:

    testImplementation("org.junit.vintage:junit-vintage-engine") {
        exclude group: "org.hamcrest", module: "hamcrest-core"
    }
    

    Equivalent changes in pom.xml would be:

    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.hamcrest</groupId>
                <artifactId>hamcrest-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>