Один простой способ поглумиться над этим, чтобы изменить мета-класс для RequestContextHolder
вернуть издеваться, когда getRequestAttributes()
называется.
Я написал простую спецификацию для этого, и был очень удивлен, когда это не сработало! Так что это оказалось довольно интересной проблемой. После некоторого расследования я обнаружил, что в этом конкретном случае есть пара подводных камней, о которых нужно знать.
При получении объекта запроса, RCH.requestAttributes.request
, вы делаете это через интерфейс RequestAttributes
который не реализует метод getRequest()
. Это прекрасно в хорошем состоянии, если возвращаемый объект действительно имеет это свойство, но не будет работать, когда высмеивает интерфейс RequestAttributes
в споке. Поэтому вам нужно высмеять интерфейс или класс, который на самом деле имеет этот метод.
Моей первой попыткой решения 1. было изменить макет типа на ServletRequestAttributes
, который имеет метод getRequest()
. Однако этот метод является окончательным. При пропуске макета со значениями для окончательного метода, заглушенные значения просто игнорируются. В этом случае было возвращено null
.
Обе эти проблемы легко преодолеть путем создания пользовательского интерфейса для этого теста, который называется MockRequestAttributes
, и использовать этот интерфейс для Мок в спецификации.
Это привело к следующему коду:
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
}
}