jeden prosty sposób na Mock nich jest modyfikacja meta klasy dla RequestContextHolder
zwrócić makiety gdy getRequestAttributes()
nazywa.
Napisałem do tego prostą specyfikację i byłem bardzo zaskoczony, kiedy to nie zadziałało! To okazało się dość interesującym problemem. Po pewnym dochodzeniu odkryłem, że w tym konkretnym przypadku jest kilka pułapek, o których należy pamiętać.
Podczas pobierania obiektu żądania, RCH.requestAttributes.request
, robisz to za pomocą interfejsu RequestAttributes
że nie implementuje metodę getRequest()
. Jest to idealnie w porządku, jeśli zwracany obiekt faktycznie ma tę właściwość, ale nie zadziała podczas kpienia z interfejsuw spocku. Będziesz więc musiał sfałszować interfejs lub klasę, która faktycznie ma tę metodę.
Moja pierwsza próba rozwiązania 1. polegała na zmianie typu próbnego na ServletRequestAttributes
, która ma metodę getRequest()
. Ta metoda jest jednak ostateczna. Po odgadnięciu makiety z wartościami dla metody ostatecznej, wartości znikające są po prostu ignorowane. W tym przypadku zwrócono null
.
Oba te problemy było łatwo przezwyciężyć, tworząc niestandardowy interfejs dla tego testu, zwany MockRequestAttributes
i używać tego interfejsu do Mock w spec.
Spowodowało to w poniższym kodzie:
import org.springframework.web.context.request.RequestContextHolder
// modified for testing
class AddressService {
def localAddress
def contentType
def update() {
def request = RequestContextHolder.requestAttributes.request
localAddress = request.localAddr
contentType = request.contentType
}
}
import org.springframework.web.context.request.RequestAttributes
import javax.servlet.http.HttpServletRequest
interface MockRequestAttributes extends RequestAttributes {
HttpServletRequest getRequest()
}
import org.springframework.web.context.request.RequestContextHolder
import spock.lang.Specification
import javax.servlet.http.HttpServletRequest
class MockRequestSpec extends Specification {
def "let's mock a request"() {
setup:
def requestAttributesMock = Mock(MockRequestAttributes)
def requestMock = Mock(HttpServletRequest)
RequestContextHolder.metaClass.'static'.getRequestAttributes = {->
requestAttributesMock
}
when:
def service = new AddressService()
def result = service.update()
then:
1 * requestAttributesMock.getRequest() >> requestMock
1 * requestMock.localAddr >> '127.0.0.1'
1 * requestMock.contentType >> 'text/plain'
service.localAddress == '127.0.0.1'
service.contentType == 'text/plain'
cleanup:
RequestContextHolder.metaClass = null
}
}