在单元测试期间注入模拟HttpServletResponse

时间:2017-04-07 16:02:26

标签: java jax-rs mockito cxf junit4

问题:如何在我的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注入到我的端点。我会注意到,在没有注入Context的端点上,测试工作正常(当我删除自定义调用程序位时)。

1 个答案:

答案 0 :(得分:1)

您不必使用构造函数初始化Example服务,只需保留:

@InjectMocks
ExampleService service;

如果你想测试@Path(&#34; / endpoint&#34;),那么它是对的你做什么但很奇怪。 如果你想测试你的代码,就这样做:

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