本文介紹了為什么用WebFlux進行的Spring Boot測試忽略了定制的Jackson模塊的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我正在編寫一個使用Spring Boot 2.0.1和WebFlux路由器函數的應用程序(不是基于注釋!)。對于我的一些數據對象,我編寫了擴展StdSerializer
的定制序列化程序。我在SimpleModule
中注冊這些組件,并將該模塊公開為一個Bean。
當我運行應用程序時,此設置非常出色。Bean被實例化,REST響應使用正確的序列化程序序列化。
現在我想編寫一個測試,以驗證路由器功能及其背后的處理程序是否按預期工作。我想嘲笑的是處理程序背后的服務。但是,在測試中,REST響應使用默認序列化程序。
我已經創建了一個復制該問題的小型演示項目。完整代碼可在此處找到:http://s000.tinyupload.com/?file_id=82815835861287011625
Gradle配置加載Spring Boot和一些依賴項以支持WebFlux和測試。
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin
import org.springframework.boot.gradle.plugin.SpringBootPlugin
buildscript {
ext {
springBootVersion = '2.0.1.RELEASE'
}
repositories {
mavenCentral()
// To allow to pull in milestone releases from Spring
maven { url 'https://repo.spring.io/milestone' }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("io.spring.gradle:dependency-management-plugin:1.0.5.RELEASE")
}
}
apply plugin: 'java'
apply plugin: SpringBootPlugin
apply plugin: DependencyManagementPlugin
repositories {
mavenCentral()
// To allow to pull in milestone releases from Spring
maven { url 'https://repo.spring.io/milestone' }
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:2.0.1.RELEASE'
}
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-webflux'
compile 'org.slf4s:slf4s-api_2.12:1.7.25'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.springframework.boot:spring-boot-starter-json'
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:2.+"
}
該數據對象有兩個字段。
package com.example.model;
public class ReverserResult {
private String originalString;
private String reversedString;
// ... constructor, getters
}
自定義序列化程序以與默認序列化程序完全不同的方式呈現數據對象。原始字段名稱消失,數據對象的內容被壓縮為單個字符串。
@Component
public class ReverserResultSerializer extends StdSerializer<ReverserResult> {
// ... Constructor ...
@Override
public void serialize(ReverserResult value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeFieldName("result");
gen.writeString(value.getOriginalString() + "|" + value.getReversedString());
gen.writeEndObject();
}
}
序列化程序包裝在Jackson模塊中并公開為Bean。在運行實際應用時,此Bean被正確拾取并添加到ObjectMapper
。
@Configuration
public class SerializerConfig {
@Bean
@Autowired public Module specificSerializers(ReverserResultSerializer reverserResultSerializer) {
SimpleModule serializerModule = new SimpleModule();
serializerModule.addSerializer(ReverserResult.class, reverserResultSerializer);
return serializerModule;
}
}
我還驗證了該Bean實際上存在于測試中。因此,我可以排除在加載Bean時缺少在測試期間創建的上下文。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ReverserRouteTest {
@Autowired
public ReverserRoutes reverserRoutes;
@MockBean
public ReverserService mockReverserService;
@Autowired
@Qualifier("specificSerializers")
public Module jacksonModule;
@Test
public void testSerializerBeanIsPresent() {
assertNotNull(jacksonModule);
}
@Test
public void testRouteAcceptsCall() {
given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));
WebTestClient client = WebTestClient.bindToRouterFunction(reverserRoutes.createRouterFunction()).build();
client.get().uri("/reverse/FooBar").exchange().expectStatus().isOk();
}
@Test
public void testRouteReturnsMockedResult() {
given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));
WebTestClient client = WebTestClient.bindToRouterFunction(reverserRoutes.createRouterFunction()).build();
client.get().uri("/reverse/somethingcompletelydifferent")
.exchange()
.expectBody().json("{"result":"foo|bar"}");
}
}
運行應用時的結果:
GET http://localhost:9090/reverse/FooBar
HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/json;charset=UTF-8
{
"result": "FooBar|raBooF"
}
運行測試時的結果:
< 200 OK
< Content-Type: [application/json;charset=UTF-8]
{"originalString":"foo","reversedString":"bar"}
我還嘗試創建我自己的ObjectMapper實例,但也沒有使用。我想知道我是不是錯過了一個設置(盡管我確實嘗試了很多注釋…)或者我是不是撞上了蟲子。我在谷歌上搜索了很多,但到目前為止,我找到的解決方案都沒有幫助。此外,到目前為止,使用路由器功能的人很少:)。
如有任何幫助,我們將不勝感激!
更新:我也嘗試過2.0.2.RELEASE和2.1.0.BUILD-20180509。結果總是相同的。
推薦答案
而不是在測試中手動創建WebTestClient
,您可以利用@AutoConfigureWebTestClient
并按如下方式自動連接它,以便正確考慮您的杰克遜模塊:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWebTestClient
public class ReverserRouteTest {
@MockBean
public ReverserService mockReverserService;
@Autowired
@Qualifier("specificSerializers")
public Module jacksonModule;
@Autowired
public WebTestClient client;
@Test
public void testSerializerBeanIsPresent() {
assertNotNull(jacksonModule);
}
@Test
public void testRouteAcceptsCall() {
given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));
client.get().uri("/reverse/FooBar").exchange().expectStatus().isOk();
}
@Test
public void testRouteReturnsMockedResult() {
given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));
client.get().uri("/reverse/somethingcompletelydifferent")
.exchange()
.expectBody().json("{"result":"foo|bar"}");
}
}
這篇關于為什么用WebFlux進行的Spring Boot測試忽略了定制的Jackson模塊的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,