使用 restAssured 测试 Spring Boot Rest 应用程序
Posted
技术标签:
【中文标题】使用 restAssured 测试 Spring Boot Rest 应用程序【英文标题】:testing spring boot rest application with restAssured 【发布时间】: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 异常。
你知道这个设置有什么问题吗?
【问题讨论】:
【参考方案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://***.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 SpringImport issues mentioned in another ***
确保你使用:
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.*;
使用错误的导入可能会导致连接被拒绝异常。
【讨论】:
以上是关于使用 restAssured 测试 Spring Boot Rest 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
java接口自动化测试--restassured如何进行文件上传接口测试
Spring Boot测试中使用REST Assured(转)
RestAssured 中的无效 JSON Schema 异常,同时针对来自 swagger 的模式进行验证