【问题标题】:testing spring boot rest application with restAssured使用 restAssured 测试 Spring Boot Rest 应用程序
【发布时间】:2017-04-01 14:38:34
【问题描述】:

我已经为此苦苦挣扎了一段时间。 我想使用 restAssured 来测试我的 SpringBoot REST 应用程序。

虽然看起来容器正常旋转,但请放心(其他任何东西似乎都无法触及它。

我总是收到 Connection denied 异常。

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)
...

我的测试课:

@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);
    }

}

现在对于奇怪的部分,test 传递并打印了它应该传递的内容,但 test2 得到了 Connection refused 异常。

你知道这个设置有什么问题吗?

【问题讨论】:

    标签: java spring rest spring-boot rest-assured


    【解决方案1】:

    "/clothes" 作为参数传递给 get() 方法应该可以解决问题

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

    【讨论】:

    • 不幸的是这并没有改变任何东西
    【解决方案2】:

    你是不是运行在一些非标准的端口上? 你有没有在你的

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

    【讨论】:

    • SpringBootTest.WebEnvironment.RANDOM_PORT 导致应用每次在不同的端口上运行
    • 那么可能是,`@Value("${local.server.port}") int port; @Before public static void init(){ RestAssured.baseURI = "localhost"; // 酌情替换 RestAssured.port = port; } `
    【解决方案3】:

    我会自己回答这个问题..

    在花费了额外的时间之后,事实证明TestRestTemplate 已经知道并设置了正确的端口。 RestAssured 不会...

    这样我就达到了以下测试运行没有任何问题的地步。

    @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);
        }
    
    }
    

    我本可以发誓我以前尝试过这样做......但我想我确实使用了其他一些注释......

    【讨论】:

    • 请注意,在 Spring 2 中,只需稍作修改即可使用:@ExtendWith(SpringExtension.class) 代替 RunWith@BeforeEach 代替 Before,当使用 Junit5 (Jupiter) 时。
    • 这个和其他答案没有考虑到使用 RANDOM_PORT 会杀死 Spring Test 的事务管理。 @Transactional 将不起作用,测试将不再被隔离。从长远来看,这将带来问题。 docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/…
    【解决方案4】:

    简单地说:

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT)
    public class CommonScenarioTest {
    
        @BeforeClass
        public static void setup() {
            RestAssured.baseURI = "http://localhost/foo";
            RestAssured.port = 8090;
        }
    

    【讨论】:

      【解决方案5】:

      基于https://stackoverflow.com/users/2838206/klubi 的回答并且不为您发出的每个请求设置端口:

      @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);
          }
      }
      

      【讨论】:

      • 请注意,在 Spring 2 中,只需稍作修改即可使用:@ExtendWith(SpringExtension.class) 代替 RunWith@BeforeEach 代替 Before 使用 Junit5 (Jupiter)。
      【解决方案6】:

      我建议在这种情况下使用@WebMvcTest,你只需要放心地模拟 mvc 依赖:

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

      使用@SpringBootTest 仅测试一个控制器是开销,所有冗余bean,如@Component@Service 等,都将被创建并 将启动完整的 HTTP 服务器。更多细节: 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
           }
       }
      

      【讨论】:

      • 现在您使用模拟/单元(容器外)测试,但问题是如何进行集成(端到端)测试
      【解决方案7】:

      我遇到了同样的问题,服务器在端口 34965(不是 8080)上运行应用程序。

      这解决了我的问题:

      @Autowired
      ServerProperties serverProperties;
      
      @Autowired
      Environment environment;
      
      public String getPath() {
          final int port = environment.getProperty("local.server.port", Integer.class);
      
          return "http://localhost:" + port;
      }
      
      @Before
      public void setUp() throws Exception {
          RestAssured.baseURI = getPath();
      }
      
      @Test
      public void testResponse(){
          response = get("/books");
      }
      

      【讨论】:

        【解决方案8】:

        您似乎正在尝试为 Spring Web App 编写集成测试。 REST-assured Support for Spring MockMvc on Baeldung 提供有关如何执行此操作的信息。

        @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);
            }
        }
        

        Baeldung 中没有提到的是 Spring 的静态导入更改。 REST-Assured Docs on Bootstrapping Spring
        Import issues mentioned in another StackOverflow

        确保你使用:

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

        不要与 Spring 一起使用:

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

        使用错误的导入可能会导致连接被拒绝异常。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-01
          • 1970-01-01
          • 2016-11-06
          • 2017-01-30
          • 1970-01-01
          • 2018-07-22
          • 2016-10-20
          相关资源
          最近更新 更多