期待の定義

次の例に示すように、リクエストの実行後に 1 つ以上の andExpect(..) 呼び出しを追加することにより、期待値を定義できます。1 つの期待が失敗するとすぐに、他の期待は主張されません。

  • Java

  • Kotlin

// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*

mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
import org.springframework.test.web.servlet.get

mockMvc.get("/accounts/1").andExpect {
	status { isOk() }
}

次の例に示すように、リクエストの実行後に andExpectAll(..) を追加することで、複数の期待値を定義できます。andExpect(..) とは対照的に、andExpectAll(..) は、提供されたすべての期待値が表明され、すべての障害が追跡および報告されることを保証します。

  • Java

  • Kotlin

// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*

mockMvc.perform(get("/accounts/1")).andExpectAll(
	status().isOk(),
	content().contentType("application/json;charset=UTF-8"));
import org.springframework.test.web.servlet.get

mockMvc.get("/accounts/1").andExpectAll {
	status { isOk() }
	content { contentType(APPLICATION_JSON) }
}

MockMvcResultMatchers.* は多くの期待を提供しますが、その中にはさらに入れ子になってさらに詳細な期待があります。

期待は 2 つの一般的なカテゴリに分類されます。アサーションの最初のカテゴリは、レスポンスのプロパティ(レスポンスステータス、ヘッダー、コンテンツなど)を検証します。これらは、主張する最も重要な結果です。

アサーションの 2 番目のカテゴリは、レスポンスを超えています。これらのアサーションにより、リクエストを処理したコントローラーメソッド、例外が発生して処理されたかどうか、モデルのコンテンツは何か、選択されたビュー、追加されたフラッシュ属性など、Spring MVC 固有の側面をインスペクションできます。また、リクエストやセッションの属性など、サーブレット固有の側面をインスペクションすることもできます。

次のテストは、バインディングまたは検証が失敗したことを表明します。

  • Java

  • Kotlin

mockMvc.perform(post("/persons"))
	.andExpect(status().isOk())
	.andExpect(model().attributeHasErrors("person"));
import org.springframework.test.web.servlet.post

mockMvc.post("/persons").andExpect {
	status { isOk() }
	model {
		attributeHasErrors("person")
	}
}

多くの場合、テストを作成するとき、実行されたリクエストの結果をダンプすることが有用です。print() は MockMvcResultHandlers からの静的インポートです。

  • Java

  • Kotlin

mockMvc.perform(post("/persons"))
	.andDo(print())
	.andExpect(status().isOk())
	.andExpect(model().attributeHasErrors("person"));
import org.springframework.test.web.servlet.post

mockMvc.post("/persons").andDo {
		print()
	}.andExpect {
		status { isOk() }
		model {
			attributeHasErrors("person")
		}
	}

リクエスト処理によって未処理の例外が発生しない限り、print() メソッドは、利用可能なすべての結果データを System.out に出力します。log() メソッドと print() メソッドの 2 つの追加バリアントもあります。1 つは OutputStream を受け入れ、もう 1 つは Writer を受け入れます。例: print(System.err) を呼び出すと結果データが System.err に出力され、print(myWriter) を呼び出すと結果データがカスタムライターに出力されます。結果データを出力する代わりにログに記録する場合は、log() メソッドを呼び出して、結果データを org.springframework.test.web.servlet.result ロギングカテゴリに単一の DEBUG メッセージとして記録します。

場合によっては、結果に直接アクセスして、他の方法では検証できないものを検証したい場合があります。これは、次の例に示すように、他のすべての期待値の後に .andReturn() を追加することで実現できます。

  • Java

  • Kotlin

MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn();
// ...
var mvcResult = mockMvc.post("/persons").andExpect { status { isOk() } }.andReturn()
// ...

すべてのテストが同じ期待値を繰り返す場合、次の例に示すように、MockMvc インスタンスを構築するときに共通の期待値を 1 回設定できます。

  • Java

  • Kotlin

standaloneSetup(new SimpleController())
	.alwaysExpect(status().isOk())
	.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
	.build()
// Not possible in Kotlin until {kotlin-issues}/KT-22208 is fixed

共通の期待は常に適用され、別の MockMvc インスタンスを作成せずに上書きすることはできません。

JSON レスポンスコンテンツに Spring HATEOAS [GitHub] (英語) で作成されたハイパーメディアリンクが含まれる場合、次の例に示すように、JsonPath 式を使用して、結果のリンクを確認できます。

  • Java

  • Kotlin

mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
	.andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people"));
mockMvc.get("/people") {
	accept(MediaType.APPLICATION_JSON)
}.andExpect {
	jsonPath("$.links[?(@.rel == 'self')].href") {
		value("http://localhost:8080/people")
	}
}

XML レスポンスコンテンツに Spring HATEOAS [GitHub] (英語) で作成されたハイパーメディアリンクが含まれている場合、XPath 式を使用して、結果のリンクを確認できます。

  • Java

  • Kotlin

Map<String, String> ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom");
mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML))
	.andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people"));
val ns = mapOf("ns" to "http://www.w3.org/2005/Atom")
mockMvc.get("/handle") {
	accept(MediaType.APPLICATION_XML)
}.andExpect {
	xpath("/person/ns:link[@rel='self']/@href", ns) {
		string("http://localhost:8080/people")
	}
}