【问题标题】:Inject mock HttpServletResponse during unit testing在单元测试期间注入模拟 HttpServletResponse
【发布时间】:2017-04-07 16:02:26
【问题描述】:

第一个问题:如何在 CXF JAX-RS 服务端点的单元测试期间注入模拟(或真实?)HttpServletResponse?

我们的服务是如何设置的示例(请注意,我无权更改非测试结构):

package services.example;

import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;

@RestController
@Path("/base")
@Produces(MediaType.APPLICATION_JSON_VALUE);
public class ExampleService {

  @Autowired
  SomeInjectedService injectedService;

  @POST
  @Path("/endpoint")
  public Object testEndpoint(Object exampleInput, @Context HttpServletResponse response) {
    if (exampleInput.someMethod != null) {
      // Exception thrown here during tests, response is null!!!
      response.setStatus(301);
      return exampleInput;
    }

    return new injectedService.returnOutputFromInput(exampleInput);
  }
}

测试类:

package test.services.example

// A gazillion imports.  Mockito, JUnit, Hamcrest, Javax.ws.rs, org.apache.cxf, Jackson providers.

public class testExampleService {

  @Mock
  private HttpServletResponse mockResponse; // Should I do this?

  @Mock
  SomeInjectedService mockInjectionService;

  @InjectMocks
  ExampleService service = new ExampleService();

  @Before
  public void setUpStuff() {
    MockitoAnnotations.initMocks(this);

    JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
    sf.setResourceClasses(ExampleService.class);

    List<Object> providers = new ArrayList<Object>;
    JacksonJsonProvider provider = new JacksonJsonProvider();
    providers.add(provider);

    sf.setProviders(providers);

    sf.setResourceProvider(ExampleService.class, new SingletonResourceProvider(service, true));
    sf.setAddress("local://someuri");

    // This is where I'm trying to set up my injected Response context.  Help?
    sf.setInvoker(new Invoker() {
      Invoker jarsInvoker = new JAXRSInvoker();

      @Override
      public Object invoke(Exchange exchange, Object o) {
        // What goes in here?  I've seen an example for setting a mock
        // Request context, but no for a Response.  Here's my current 
        // (broken) attempt to do this...
        exchange.getInMessage().put(AbstractHTTPDestination.HTTP_RESPONSE, mockResponse);
        return jarsInvoker.invoke(exchange, o);
      }
    });
  }

  @Test
  public void testEndpointShouldReturn301() {
    List<Object> providers = new ArrayList<Object>();
    JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
    providers.add(provider);

    WebClient client = WebClient.create("local://someuri", providers);
    WebClient.getConfig(client)
             .getRequestContext()
             .put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);

    // Exception thrown here, Response context doesn't get injected!
    client.path("/base/endpoint");
    SomeTestObject obj = new SomeTestObject();
    Response response = client.type(MediaType.APPLICATION_JSON).post(obj);

    // Never gets run because an exception was thrown :(
    assertThat(response.getStatus(), is(301));
  }

}

我可能在这里做错了几件事,但我希望我只需要在我的自定义 Invoker 中使用正确的“魔法”,以便正确地将 HttpServletResponse 注入我的端点。我会注意到,在我没有注入上下文的端点上,测试可以正常工作(当我删除我的自定义调用程序位时)。

【问题讨论】:

    标签: java jax-rs mockito cxf junit4


    【解决方案1】:

    您不必使用构造函数初始化示例服务,只需保留以下内容:

    @InjectMocks
    ExampleService service;
    

    如果你想测试@Path("/endpoint"),那么你做什么是对的,但很奇怪。 如果您想测试您的代码,只需这样做:

      @Test
      public void testEndpointShouldReturn301() {
        service.testEndpoint(someObject, mockResponse);
        assertThat(response.getStatus(), is(301));
      }
    

    【讨论】:

    • 感谢您的回答,但测试的目的是确保对给定端点的 REST 调用达到预期的回调函数。在测试期间检查 - 在我的示例中 - 到“/endpoint”的 POST 始终触发 testEndpoint() 方法非常重要。
    猜你喜欢
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 2017-03-19
    • 2021-04-05
    • 1970-01-01
    相关资源
    最近更新 更多