testing spring boot rest application with restAssured

17,722

Solution 1

I'll answer this question myself..

After spending additional amount of time on it it turned out that TestRestTemplate already knows and sets proper port. RestAssured does not...

With that I got to a point where below test runs without any issues.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SizesRestControllerIT {

    @LocalServerPort
    int port;

    @Before
    public void setUp() {
        RestAssured.port = port;
    }

    @Test
    public void test2() throws InterruptedException {
        given().basePath("/clothes").get("").then().statusCode(200);
    }

}

I could have sworn I tried doing it this way previously... But I guess I did use some other annotations with this...

Solution 2

Based on https://stackoverflow.com/users/2838206/klubi answer and to not set the port for every request that you make:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = 
SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SizesRestControllerIT {

    @LocalServerPort
    int port;

    @Before
    public void setUp() {
        RestAssured.port = port;
    }

    @Test
    public void test2() throws InterruptedException {
        given().basePath("/clothes").get("").then().statusCode(200);
    }
}

Solution 3

are you running on some non-standard port may be? have you tried this in your

@Before public static void init(){ RestAssured.baseURI = "http://localhost"; // replace as appropriate RestAssured.port = 8080; }

Solution 4

I'd recommend to use @WebMvcTest for that case, all you need is to have rest assured mock mvc dependency:

<dependency>
            <groupId>com.jayway.restassured</groupId>
            <artifactId>spring-mock-mvc</artifactId>
            <version>${rest-assured.version}</version>
            <scope>test</scope>
</dependency>

Using of @SpringBootTest to test just a controller is overhead, all redundant beans, like @Component, @Service, etc, will be created and a full HTTP server will be started. For more details: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests;

  @RunWith(SpringRunner.class)
  @WebMvcTest(value = SizesRestController.class)
  public class SizesRestControllerIT {

     @Autowired
     private MockMvc mvc;

     @Before
     public void setUp() {
        RestAssuredMockMvc.mockMvc(mvc);
     }

     @Test
     public void test() {
        RestAssuredMockMvc.given()
           .when()
           .get("/clothes")
           .then()
           .statusCode(200);
        // do some asserts
     }
 }

Solution 5

It looks like you are trying to write an integration test for a Spring Web App. REST-assured Support for Spring MockMvc on Baeldung has information on how to do this.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class SizesRestControllerIT {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void initialiseRestAssuredMockMvcWebApplicationContext() {
        RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
    }

    @Test
    public void test2() throws InterruptedException {
        given().basePath("/clothes").get("").then().statusCode(200);
    }
}

What is not mentioned in Baeldung is the static imports change for Spring. REST-Assured Docs on Bootstrapping Spring
Import issues mentioned in another StackOverflow

Make sure you use:

import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;
import static io.restassured.module.mockmvc.matcher.RestAssuredMockMvcMatchers.*;

Do not use with Spring:

import static io.restassured.RestAssured.*;
import static io.restassured.matcher.RestAssuredMatchers.*;

Using the wrong imports can cause the connection refused exception.

Share:
17,722

Related videos on Youtube

klubi
Author by

klubi

Updated on February 23, 2022

Comments

  • klubi
    klubi about 2 years

    I've been struggling with this for some time now. I'd like to use restAssured to test my SpringBoot REST application.

    While it looks like container spins up properly, rest assured (and anything else seems to have problems reaching out to it.

    All the time I'm getting Connection refused exception.

    java.net.ConnectException: Connection refused
    
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    ...
    

    my test class:

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class SizesRestControllerIT {
    
        @Autowired
        private TestRestTemplate restTemplate;
    
        @Test
        public void test() {
            System.out.println(this.restTemplate.getForEntity("/clothes", List.class));
        }
    
        @Test
        public void test2() throws InterruptedException {
            given().basePath("/clothes").when().get("").then().statusCode(200);
        }
    
    }
    

    and now for the weird part, test passes and prints what it should, but test2 is getting Connection refused exception.

    Any ideas what is wrong with this setup?

  • klubi
    klubi over 7 years
    unfortunately this did not change anything
  • klubi
    klubi over 7 years
    SpringBootTest.WebEnvironment.RANDOM_PORT causes app to run on different port each time
  • ameet chaubal
    ameet chaubal over 7 years
    then may be, ` @Value("${local.server.port}") int port; @Before public static void init(){ RestAssured.baseURI = "localhost"; // replace as appropriate RestAssured.port = port; } `
  • Muhammad Hewedy
    Muhammad Hewedy about 5 years
    Now you using mock/unit (out-of-container) testing, however, the question is asking about how to do integration (end-to-end) testing
  • Randy
    Randy almost 4 years
    Note that with Spring 2 this works with minor modification: @ExtendWith(SpringExtension.class) instead of RunWith and @BeforeEach instead of Before when using Junit5 (Jupiter).
  • Randy
    Randy almost 4 years
    Note that with Spring 2 this works with minor modification: @ExtendWith(SpringExtension.class) instead of RunWith and @BeforeEach instead of Before when using Junit5 (Jupiter).
  • Martín Coll
    Martín Coll over 3 years
    This and other answers don't take into account that using RANDOM_PORT will kill Spring Test's transaction management. @Transactional won't work and tests won't be isolated anymore. This will present problems in the long run. docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html‌​/…