Openejb使用异常映射器进行休息集成测试

时间:2012-10-26 12:50:46

标签: exception-handling junit jax-rs openejb

我正在为我的jax-rs服务编写一些集成测试,其中我有一组异常映射器。因此,在执行给定请求时,我期望基于异常映射器的某个响应代码。问题是我无法在此环境中运行时调用异常映射器。

我的服务应该在我的测试中引发逻辑错误:

@Stateless
@Path("/baseCustomer")
public class BaseCustomerService {
    @EJB //this one gets mocked in the unittest
    private BaseCustomerManagerBean customerManager;

    @POST
    @Path("crud")
    @Consumes({MediaType.APPLICATION_XML})
    @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
    public Hkunde createCustomer(Hkunde newCustomer) throws LogicalException {
        //throws exception according to mocking
        return customerManager.createCustomer(newCustomer); 
    }

异常映射器:

@Provider
public class LogicalExceptionMapper implements ExceptionMapper<LogicalException> {

    @Override
    public Response toResponse(LogicalException exception) {
        return Response.status(Response.Status.FORBIDDEN).build();
    }
} 

我设置了这样的测试:

@Mock
private BaseCustomerManagerBean baseCustomerManager;
private HttpClient httpClient;
private BaseCustomerServiceClient client;

@Configuration
public Properties config() throws Exception {
    Properties properties = new Properties();
    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
    properties.setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, Boolean.TRUE.toString());

    properties.setProperty(DeploymentFilterable.CLASSPATH_INCLUDE, LogicalExceptionMapper.class.getName());
    properties.setProperty("openejb.jaxrs.providers.auto", "true");
    properties.setProperty("openejb.servicemanager.enabled", "true");
    return properties;
}

@MockInjector
public Class<?> mockitoInjector() {
    return MockitoInjector.class;
}

@Module
public EjbModule createModule() throws Exception {
    final StatelessBean bean = (StatelessBean) new StatelessBean(BaseCustomerService.class).localBean();
    bean.setRestService(true);

    final EjbJar ejbJar = new EjbJar();
    ejbJar.addEnterpriseBean(bean);

    final OpenejbJar openejbJar = new OpenejbJar();
    openejbJar.addEjbDeployment(new EjbDeployment(ejbJar.getEnterpriseBeans()[0]));

    EjbModule module = new EjbModule(ejbJar);
    module.setOpenejbJar(openejbJar);

    return module;
}
@Module
public Class[] exceptionMappers() {
    return new Class[]{LogicalExceptionMapper.class};
}

@Before
public void setup() {
    ServiceHost serviceHost = new ServiceHost("http://localhost:4204/BaseCustomerServiceTest");
    httpClient = new HttpClient(serviceHost);
    client = new BaseCustomerServiceClient(httpClient);
}

@Test
public void createCustomer_givenLogicalException_expectsLogicalException() throws LogicalException {
    Hkunde expected = new Hkunde(true);

    when(baseCustomerManager.createCustomer(expected)).thenThrow(new LogicalException("mock"));

    try {
        client.createCustomer(expected);
        fail("Expected LogicalException");
    } catch (LogicalException ex) {
    }

    verify(baseCustomerManager).createCustomer(expected);
}

因此,当我执行测试时,我的client将从响应中读取响应代码并根据此代码抛出异常。

问题是永远不会调用异常映射器,并且我总是收到500内部服务器错误,而不是“禁止”响应。我猜我在设置ejbjar或类似的东西时需要添加更多信息。

谢谢!

1 个答案:

答案 0 :(得分:1)

此示例http://svn.apache.org/repos/asf/openejb/trunk/openejb/examples/rest-applicationcomposer/src/test/java/org/superbiz/composed/rest/GreetingServiceTest.java(通过http://rmannibucau.wordpress.com/2012/09/13/use-mockito-with-openejb/ ;-))显示您想要的内容。

openejbJar.addEjbDeployment(...之后添加以下内容,它应该有效。

final Properties properties = openejbJar.getEjbDeployment().iterator().next().getProperties();
properties.setProperty("cxf.jaxrs.providers", LogicalExceptionMapper.class.getName());

这是一个最小的工作示例(使用openejb-cxf-rs 4.5.0和openejb-core 4.5.0):

import java.util.Properties;
import javax.ejb.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.openejb.OpenEjbContainer;
import org.apache.openejb.config.EjbModule;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.StatelessBean;
import org.apache.openejb.jee.oejb3.EjbDeployment;
import org.apache.openejb.jee.oejb3.OpenejbJar;
import org.apache.openejb.junit.ApplicationComposer;
import org.apache.openejb.junit.Configuration;
import org.apache.openejb.junit.Module;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(ApplicationComposer.class)
public class RestWithExceptionMapper {

    @Configuration
    public Properties configuration() {
        return new Properties() {
            {
                setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, Boolean.TRUE.toString());
            }
        };
    }

    @Module
    public EjbModule app() {
        final StatelessBean bean = (StatelessBean) new StatelessBean(MyResource.class).localBean();
        bean.setRestService(true);
        final EjbJar ejbJar = new EjbJar();
        ejbJar.addEnterpriseBean(bean);
        final OpenejbJar openejbJar = new OpenejbJar();
        openejbJar.addEjbDeployment(new EjbDeployment(ejbJar.getEnterpriseBeans()[0]));
        final Properties properties = openejbJar.getEjbDeployment().iterator().next().getProperties();
        properties.setProperty("cxf.jaxrs.providers", MyExceptionMapper.class.getName());
        final EjbModule module = new EjbModule(ejbJar);
        module.setOpenejbJar(openejbJar);
        return module;
    }

    public static class FooException extends RuntimeException {
    }

    public static class MyExceptionMapper implements ExceptionMapper<FooException> {

        @Override
        public Response toResponse(final FooException t) {
            return Response.ok("Objection!").build();
        }
    }

    @Path(value = "/test")
    public static class MyResource {

        @GET
        @Path(value = "/throw")
        public String throwException() {
            throw new FooException();
        }
    }

    @Test
    public void checkServiceWasDeployed() {
        assertEquals("Objection!", WebClient.create("http://localhost:4204/RestWithExceptionMapper").path("/test/throw").get(String.class));
    }
}