我正在为我的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或类似的东西时需要添加更多信息。
谢谢!
答案 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));
}
}