Một cách đơn giản để nhạo báng này, là để sửa đổi các lớp meta cho RequestContextHolder
để trả về một giả khi getRequestAttributes()
được gọi.
Tôi đã viết một thông số kỹ thuật đơn giản để thực hiện việc này và khá ngạc nhiên khi nó không hoạt động! Vì vậy, điều này hóa ra lại là một vấn đề khá thú vị. Sau một số cuộc điều tra, tôi thấy rằng trong trường hợp đặc biệt này, có một vài cạm bẫy cần lưu ý.
Khi bạn lấy đối tượng yêu cầu, RCH.requestAttributes.request
, bạn đang làm như vậy thông qua một giao diện RequestAttributes
mà không thực hiện phương pháp getRequest()
. Điều này là hoàn toàn tốt trong groovy nếu đối tượng trả về thực sự có thuộc tính này, nhưng sẽ không hoạt động khi chế nhạo giao diện RequestAttributes
trong spock. Vì vậy, bạn sẽ cần phải giả lập một giao diện hoặc một lớp thực sự có phương pháp này.
Lần đầu tiên tôi giải quyết 1., là thay đổi loại mô hình thành ServletRequestAttributes
, có phương thức getRequest()
. Tuy nhiên, phương pháp này là cuối cùng. Khi bố trí một mô hình với các giá trị cho một phương thức cuối cùng, các giá trị gốc được bỏ qua. Trong trường hợp này, null
đã được trả lại.
Cả hai vấn đề này dễ dàng khắc phục bằng cách tạo giao diện tùy chỉnh cho thử nghiệm này, được gọi là MockRequestAttributes
và sử dụng giao diện này cho Mô hình trong thông số.
Điều này dẫn đến đoạn mã sau:
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
}
}