Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Kotlin DSL support for MockMVC andExpectAll #29727

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,12 @@ class MockMvcResultMatchersDsl internal constructor (private val actions: Result
fun match(matcher: ResultMatcher) {
actions.andExpect(matcher)
}

/**
* @since 6.0.4
* @see ResultActions.andExpectAll
simonbasle marked this conversation as resolved.
Show resolved Hide resolved
*/
fun matchAll(vararg matchers: ResultMatcher) {
simonbasle marked this conversation as resolved.
Show resolved Hide resolved
actions.andExpectAll(*matchers)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,35 @@ class ResultActionsDsl internal constructor (private val actions: ResultActions,
return this
}


/**
* Provide access to [MockMvcResultMatchersDsl] Kotlin DSL.
* @since 6.0.4
* @see MockMvcResultMatchersDsl.matchAll
simonbasle marked this conversation as resolved.
Show resolved Hide resolved
*/
fun andExpectAll(dsl: MockMvcResultMatchersDsl.() -> Unit): ResultActionsDsl {
simonbasle marked this conversation as resolved.
Show resolved Hide resolved
val softMatchers = mutableListOf<ResultMatcher>()
val softActions = object : ResultActions {
override fun andExpect(matcher: ResultMatcher): ResultActions {
softMatchers.add(matcher)
return this
}

override fun andDo(handler: ResultHandler): ResultActions {
throw UnsupportedOperationException("andDo should not be part of andExpectAll DSL calls")
}

override fun andReturn(): MvcResult {
throw UnsupportedOperationException("andReturn should not be part of andExpectAll DSL calls")
}

}
// the use of softActions as the matchers DSL actions parameter will store ResultMatchers in list
MockMvcResultMatchersDsl(softActions).dsl()
actions.andExpectAll(*softMatchers.toTypedArray())
return this;
}

/**
* Provide access to [MockMvcResultHandlersDsl] Kotlin DSL.
* @see MockMvcResultHandlersDsl.handle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.test.web.servlet

import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatCode
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.hamcrest.CoreMatchers
import org.junit.jupiter.api.Test
Expand All @@ -25,6 +26,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.MediaType.APPLICATION_ATOM_XML
import org.springframework.http.MediaType.APPLICATION_JSON
import org.springframework.http.MediaType.APPLICATION_XML
import org.springframework.http.MediaType.TEXT_PLAIN
import org.springframework.test.web.Person
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.bind.annotation.GetMapping
Expand Down Expand Up @@ -97,6 +99,24 @@ class MockMvcExtensionsTests {
assertThat(handlerInvoked).isTrue()
}

@Test
fun `request with two custom matchers and matchAll`() {
var matcher1Invoked = false
var matcher2Invoked = false
val matcher1 = ResultMatcher { matcher1Invoked = true; throw AssertionError("expected") }
val matcher2 = ResultMatcher { matcher2Invoked = true }
assertThatExceptionOfType(AssertionError::class.java).isThrownBy {
mockMvc.request(HttpMethod.GET, "/person/{name}", "Lee")
.andExpect {
matchAll(matcher1, matcher2)
}
}
.withMessage("expected")

assertThat(matcher1Invoked).describedAs("matcher1").isTrue()
assertThat(matcher2Invoked).describedAs("matcher2").isTrue()
}

@Test
fun get() {
mockMvc.get("/person/{name}", "Lee") {
Expand Down Expand Up @@ -183,6 +203,22 @@ class MockMvcExtensionsTests {
}
}

@Test
fun `andExpectAll reports multiple assertion errors`() {
assertThatCode {
mockMvc.request(HttpMethod.GET, "/person/{name}", "Lee") {
accept = APPLICATION_JSON
}.andExpectAll {
status { is4xxClientError() }
content { contentType(TEXT_PLAIN) }
jsonPath("$.name") { value("Lee") }
}
}
.hasMessage("Multiple Exceptions (2):\n" +
"Range for response status value 200 expected:<CLIENT_ERROR> but was:<SUCCESSFUL>\n" +
"Content type expected:<text/plain> but was:<application/json>")
}


@RestController
private class PersonController {
Expand Down