Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
普通程序员一名
spring-framework
提交
4982b5fc
S
spring-framework
项目概览
普通程序员一名
/
spring-framework
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4982b5fc
编写于
3月 16, 2021
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve docs on SSE tests for Spring MVC
Closes gh-26687
上级
f7678cdc
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
114 addition
and
19 deletion
+114
-19
spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/AsyncTests.java
...est/web/servlet/samples/client/standalone/AsyncTests.java
+14
-13
spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/SseTests.java
.../test/web/servlet/samples/client/standalone/SseTests.java
+71
-0
src/docs/asciidoc/testing.adoc
src/docs/asciidoc/testing.adoc
+29
-6
未找到文件。
spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/AsyncTests.java
浏览文件 @
4982b5fc
/*
* Copyright 2002-202
0
the original author or authors.
* Copyright 2002-202
1
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -32,6 +32,7 @@ import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
import
org.springframework.util.concurrent.ListenableFuture
;
import
org.springframework.util.concurrent.ListenableFutureTask
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -99,7 +100,7 @@ public class AsyncTests {
}
@Test
public
void
deferredResultWithImmediateValue
()
throws
Exception
{
public
void
deferredResultWithImmediateValue
()
{
this
.
testClient
.
get
()
.
uri
(
"/1?deferredResultWithImmediateValue=true"
)
.
exchange
()
...
...
@@ -109,7 +110,7 @@ public class AsyncTests {
}
@Test
public
void
deferredResultWithDelayedError
()
throws
Exception
{
public
void
deferredResultWithDelayedError
()
{
this
.
testClient
.
get
()
.
uri
(
"/1?deferredResultWithDelayedError=true"
)
.
exchange
()
...
...
@@ -118,7 +119,7 @@ public class AsyncTests {
}
@Test
public
void
listenableFuture
()
throws
Exception
{
public
void
listenableFuture
()
{
this
.
testClient
.
get
()
.
uri
(
"/1?listenableFuture=true"
)
.
exchange
()
...
...
@@ -142,17 +143,17 @@ public class AsyncTests {
@RequestMapping
(
path
=
"/{id}"
,
produces
=
"application/json"
)
private
static
class
AsyncController
{
@
Reques
tMapping
(
params
=
"callable"
)
@
Ge
tMapping
(
params
=
"callable"
)
public
Callable
<
Person
>
getCallable
()
{
return
()
->
new
Person
(
"Joe"
);
}
@
Reques
tMapping
(
params
=
"streaming"
)
@
Ge
tMapping
(
params
=
"streaming"
)
public
StreamingResponseBody
getStreaming
()
{
return
os
->
os
.
write
(
"name=Joe"
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
@
Reques
tMapping
(
params
=
"streamingSlow"
)
@
Ge
tMapping
(
params
=
"streamingSlow"
)
public
StreamingResponseBody
getStreamingSlow
()
{
return
os
->
{
os
.
write
(
"name=Joe"
.
getBytes
());
...
...
@@ -166,41 +167,41 @@ public class AsyncTests {
};
}
@
Reques
tMapping
(
params
=
"streamingJson"
)
@
Ge
tMapping
(
params
=
"streamingJson"
)
public
ResponseEntity
<
StreamingResponseBody
>
getStreamingJson
()
{
return
ResponseEntity
.
ok
().
contentType
(
MediaType
.
APPLICATION_JSON
)
.
body
(
os
->
os
.
write
(
"{\"name\":\"Joe\",\"someDouble\":0.5}"
.
getBytes
(
StandardCharsets
.
UTF_8
)));
}
@
Reques
tMapping
(
params
=
"deferredResult"
)
@
Ge
tMapping
(
params
=
"deferredResult"
)
public
DeferredResult
<
Person
>
getDeferredResult
()
{
DeferredResult
<
Person
>
result
=
new
DeferredResult
<>();
delay
(
100
,
()
->
result
.
setResult
(
new
Person
(
"Joe"
)));
return
result
;
}
@
Reques
tMapping
(
params
=
"deferredResultWithImmediateValue"
)
@
Ge
tMapping
(
params
=
"deferredResultWithImmediateValue"
)
public
DeferredResult
<
Person
>
getDeferredResultWithImmediateValue
()
{
DeferredResult
<
Person
>
result
=
new
DeferredResult
<>();
result
.
setResult
(
new
Person
(
"Joe"
));
return
result
;
}
@
Reques
tMapping
(
params
=
"deferredResultWithDelayedError"
)
@
Ge
tMapping
(
params
=
"deferredResultWithDelayedError"
)
public
DeferredResult
<
Person
>
getDeferredResultWithDelayedError
()
{
DeferredResult
<
Person
>
result
=
new
DeferredResult
<>();
delay
(
100
,
()
->
result
.
setErrorResult
(
new
RuntimeException
(
"Delayed Error"
)));
return
result
;
}
@
Reques
tMapping
(
params
=
"listenableFuture"
)
@
Ge
tMapping
(
params
=
"listenableFuture"
)
public
ListenableFuture
<
Person
>
getListenableFuture
()
{
ListenableFutureTask
<
Person
>
futureTask
=
new
ListenableFutureTask
<>(()
->
new
Person
(
"Joe"
));
delay
(
100
,
futureTask
);
return
futureTask
;
}
@
Reques
tMapping
(
params
=
"completableFutureWithImmediateValue"
)
@
Ge
tMapping
(
params
=
"completableFutureWithImmediateValue"
)
public
CompletableFuture
<
Person
>
getCompletableFutureWithImmediateValue
()
{
CompletableFuture
<
Person
>
future
=
new
CompletableFuture
<>();
future
.
complete
(
new
Person
(
"Joe"
));
...
...
spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/SseTests.java
0 → 100644
浏览文件 @
4982b5fc
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.test.web.servlet.samples.client.standalone
;
import
org.junit.jupiter.api.Test
;
import
reactor.core.publisher.Flux
;
import
reactor.test.StepVerifier
;
import
org.springframework.test.web.Person
;
import
org.springframework.test.web.reactive.server.FluxExchangeResult
;
import
org.springframework.test.web.reactive.server.WebTestClient
;
import
org.springframework.test.web.servlet.client.MockMvcWebTestClient
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
static
java
.
time
.
Duration
.
ofMillis
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* SSE controller tests with MockMvc and WebTestClient.
*
* @author Rossen Stoyanchev
*/
public
class
SseTests
{
private
final
WebTestClient
testClient
=
MockMvcWebTestClient
.
bindToController
(
new
SseController
()).
build
();
@Test
public
void
sse
()
{
FluxExchangeResult
<
Person
>
exchangeResult
=
this
.
testClient
.
get
()
.
uri
(
"/persons"
)
.
exchange
()
.
expectStatus
().
isOk
()
.
expectHeader
().
contentType
(
"text/event-stream"
)
.
returnResult
(
Person
.
class
);
StepVerifier
.
create
(
exchangeResult
.
getResponseBody
())
.
expectNext
(
new
Person
(
"N0"
),
new
Person
(
"N1"
),
new
Person
(
"N2"
))
.
expectNextCount
(
4
)
.
consumeNextWith
(
person
->
assertThat
(
person
.
getName
()).
endsWith
(
"7"
))
.
thenCancel
()
.
verify
();
}
@RestController
private
static
class
SseController
{
@GetMapping
(
path
=
"/persons"
,
produces
=
"text/event-stream"
)
public
Flux
<
Person
>
getPersonStream
()
{
return
Flux
.
interval
(
ofMillis
(
100
)).
take
(
50
).
onBackpressureBuffer
(
50
)
.
map
(
index
->
new
Person
(
"N"
+
index
));
}
}
}
src/docs/asciidoc/testing.adoc
浏览文件 @
4982b5fc
...
...
@@ -7471,12 +7471,35 @@ or reactive type such as Reactor `Mono`:
[[spring-mvc-test-vs-streaming-response]]
===== Streaming Responses
There are no options built into Spring MVC Test for container-less testing of streaming
responses. However you can test streaming requests through the <<WebTestClient>>.
This is also supported in Spring Boot where you can
{doc-spring-boot}/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server[test a running server]
with `WebTestClient`. One extra advantage is the ability to use the `StepVerifier` from
project Reactor that allows declaring expectations on a stream of data.
The best way to test streaming responses such as Server-Sent Events is through the
<<WebTestClient>> which can be used as a test client to connect to a `MockMvc` instance
to perform tests on Spring MVC controllers without a running server. For example:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
WebTestClient client = MockMvcWebTestClient.bindToController(new SseController()).build();
FluxExchangeResult<Person> exchangeResult = client.get()
.uri("/persons")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType("text/event-stream")
.returnResult(Person.class);
// Use StepVerifier from Project Reactor to test the streaming response
StepVerifier.create(exchangeResult.getResponseBody())
.expectNext(new Person("N0"), new Person("N1"), new Person("N2"))
.expectNextCount(4)
.consumeNextWith(person -> assertThat(person.getName()).endsWith("7"))
.thenCancel()
.verify();
----
`WebTestClient` can also connect to a live server and perform full end-to-end integration
tests. This is also supported in Spring Boot where you can
{doc-spring-boot}/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server[test a running server].
[[spring-mvc-test-server-filters]]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录