Search code examples
spring-bootintellij-ideaspring-webtestclient

spring boot WebTestClient throws "No qualifying bean of type 'org.springframework.test.web.reactive.server.WebTestClient' available"


Several people have had similar problems, but what was marked as a solution for them did not solve the problem for me.

Pom.xml:

:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
            <scope>test</scope>
        </dependency>
:

CustomerControllerTest2.java

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;

import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
public class CustomerControllerTest2 {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void shouldReturnManyCustomers(){
        this.webTestClient
                .get()
                .uri("/customers")
                .header(ACCEPT,APPLICATION_JSON_VALUE)
                .exchange()
                .expectStatus()
                .is2xxSuccessful()
                .expectHeader()
                .contentType(APPLICATION_JSON)
                .expectBody()
                .jsonPath("$.length()").isNumber()
                .jsonPath("$[0].id").isEqualTo(1);
    }
}

According to others, the solution is to add "@AutoConfigureWebTestClient" and "@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)"

But this did not help.

When I use TestRestTemplate I have no issues, e.g. the below works out of the box:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class CustomerControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void greetingShouldReturnDefaultMessage() throws Exception {
        assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/customers",
                String.class)).contains("[email protected]");

    }

}

These docs:

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-running-server

say the following will work:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Hello World");
    }

}

But this also gives the same "No qualifying bean of type 'org.springframework.test.web.reactive.server.WebTestClient' available: expected at least 1 bean which qualifies as autowire candidate."

Interestingly, if I run "mvn test" both TestRestTemplate and TesWebClient tests work. If I run the tests using intellij, it fails. In intellij, it doesnt seem to know how to run anything by default, but there is an "All in package" run configuration under junit which is the only way I can see to run the tests, and this runs all TestRestTemplate tests no problem, but all WebTestClient basted tests fails with the no qualifying bean issue.


Solution

  • @AutoConfigureWebTestClient is intended for use with a mock web environment. From its javadoc:

    Annotation that can be applied to a test class to enable a WebTestClient that is bound directly to the application. Tests do not rely upon an HTTP server and use mock requests and responses.

    You are contradicting this by using @AutoConfigureWebTestClient and webEnvironment = WebEnvironment.RANDOM_PORT in combination. Instead, you could use @SpringBootTest with its default, mock web environment:

    @SpringBootTest
    @AutoConfigureWebTestClient
    public class CustomerControllerTest {
    

    You can learn more about this in the reference documentation.