Java 如何使用标头模拟 HttpServletRequest?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37314469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:12:03  来源:igfitidea点击:

How to mock HttpServletRequest with Headers?

javaunit-testingmockito

提问by Sat

I am using Mockito with Junit to test the application, I need to add headers to the HttpServletRequest while mocking. This is the first time I am using mock concept to test the application. How can we set headers to request object while using this mock concept?

我正在使用带有 Junit 的 Mockito 来测试应用程序,我需要在模拟时向 HttpServletRequest 添加标头。这是我第一次使用模拟概念来测试应用程序。在使用这个模拟概念时,我们如何设置标头来请求对象?

Java Code:

Java代码:

@Produces({ MediaType.APPLICATION_JSON })
@Path("/devices")
public class DvrRestService {
    private static final Logger logger = LoggerFactory.getLogger(DvrRestService.class);

    private DvrMiddleService dvrMiddleService;

    @Inject
    public DvrRestService(DvrMiddleService dvrMiddleService) {
        this.dvrMiddleService = dvrMiddleService;
    }

    @GET 
    @Path("/{deviceId}/metadata")
    public Response getDeviceMetadata(@Context HttpServletRequest request, @PathParam("deviceId") String deviceId,
        @RequiredSession final Session session) {

        try {
            public static String[] REQUEST_HEADERS = { "if-none-match" };
            List<String> requiredHeaders = Lists.newArrayList(REQUEST_HEADERS);
            Map<String, String> headers = new HashMap<String, String>();

            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) { // here gettting NullPointerException

                String headerName = headerNames.nextElement();
                if (requiredHeaders.contains(headerName.toLowerCase())) {
                    String value = request.getHeader(headerName);
                    if (value != null) {
                        headers.put(headerName, value);
                        System.out.println("headerName: " + headerName + ", Value: " + value);
                    }
                }
            }
            DvrResponse response = dvrMiddleService.getDeviceMetadata(deviceId.toUpperCase(), getHeaders(request));
            return processResponse(response.statusCode, response.getResponse(), DeviceMetadataResponse.class,
                response.getHeaders());
        } catch (Exception e) {
            return processErrorResponse(e, new DeviceMetadataResponse(), logger);
        }

    }
}

Here is my Test Code :

这是我的测试代码:

public class DvrRestServiceTest {

    static DvrMiddleService dms;
    static HttpServletRequest request;
    static Session session;
    static DvrRestService drs;
    public static final String DeviceId = "000004D42070";
    @BeforeClass
    public static void init(){
        dms = mock(DvrMiddleService.class);
        request = mock(HttpServletRequest.class);
        session = mock(Session.class);
        drs = new DvrRestService(dms);
    }
    @Test
    public void getDeviceMetadataTest(){
        Response rs = drs.getDeviceMetadata(request, DeviceId, session);
        assertEquals(Response.Status.OK, rs.getStatus());
    }
}

采纳答案by SubOptimal

As a starting point and demonstration for the principal you can start with the following snippet.

作为主体的起点和演示,您可以从以下代码段开始。

// define the headers you want to be returned
Map<String, String> headers = new HashMap<>();
headers.put(null, "HTTP/1.1 200 OK");
headers.put("Content-Type", "text/html");

// create an Enumeration over the header keys
Iterator<String> iterator = headers.keySet().iterator();
Enumeration headerNames = new Enumeration<String>() {
    @Override
    public boolean hasMoreElements() {
        return iterator.hasNext();
    }

    @Override
    public String nextElement() {
        return iterator.next();
    }
};

// mock HttpServletRequest
HttpServletRequest request = mock(HttpServletRequest.class);
// mock the returned value of request.getHeaderNames()
when(request.getHeaderNames()).thenReturn(headerNames);

System.out.println("demonstrate output of request.getHeaderNames()");
while (headerNames.hasMoreElements()) {
    System.out.println("header name: " + headerNames.nextElement());
}

// mock the returned value of request.getHeader(String name)
doAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        return headers.get((String) args[0]);
    }
}).when(request).getHeader("Content-Type");

System.out.println("demonstrate output of request.getHeader(String name)");
String headerName = "Content-Type";
System.out.printf("header name: [%s]   value: [%s]%n", 
        headerName, request.getHeader(headerName));
}

output

输出

demonstrate output of request.getHeaderNames()
header name: null
header name: Content-Type

demonstrate output of request.getHeader(String name)
header name: [Content-Type]   value: [text/html]

回答by Jason Slobotski

I know the OP is using Mockito. This answer is for those using spock. You can accomplish this pretty easily.

我知道 OP 正在使用 Mockito。这个答案适用于那些使用 spock 的人。你可以很容易地做到这一点。

class MyTestSpec extends Specification {

    HttpServletRequest request = Mock()
    MyTestClass myTestClass = new MyTestClass()

    def 'my test'() {
        setup:
        String expectedHeader = "x-mycustom-header"

        when:
        String someResult = myTestClass.someTestMethod()

        then:
        // here is where you return your header from the mocked request
        1 * request.getHeader(_ as String) >> expectedHeader
    }
}