Spring单元测试,内嵌RESTEasy服务的实现

jopen 12年前

  • RESTEasy介绍

RESTEasy是JBoss的一个开源项目,提供各种框架帮助你构建RESTful Web Services和RESTful Java应用程序。它是JAX-RS规范的一个完整实现并通过JCP认证。作为一个JBOSS的项目,它当然能和JBOSS应用服务器很好地集成在一起。但是,它也能在任何运行JDK5或以上版本的Servlet容器中运行。RESTEasy还提供一个RESTEasy JAX-RS客户端调用框架。能够很方便与EJB、Seam、Guice、Spring和Spring MVC集成使用。支持在客户端与服务器端自动实现GZIP解压缩。

  • 内嵌单个服务代码

在前面的文章介绍的基础上,实现SpringJUnit4ClassRunner

import java.lang.annotation.Annotation;  import java.lang.annotation.ElementType;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;  import java.util.Collections;  import java.util.List;    import org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer;  import org.junit.runner.notification.RunNotifier;  import org.junit.runners.model.InitializationError;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;    public class ResteasyEmbededServer extends SpringJUnit4ClassRunner {        private TJWSEmbeddedJaxrsServer server = new TJWSEmbeddedJaxrsServer();        public ResteasyEmbededServer(Class<?> clazz) throws InitializationError {          super(clazz);      }        @Override      public void run(RunNotifier notifier) {          int port = findAnnotationValueByClass(Port.class).value();          Class[] resourceClasses = findAnnotationValueByClass(Resources.class).value();            startServer(port, resourceClasses);          try {              super.run(notifier);          } finally {              server.stop();          }      }        private void startServer(int port, Class[] resourceClasses) {          server.setPort(port);          List<Class> actualResourceClasses = server.getDeployment().getActualResourceClasses();          Collections.addAll(actualResourceClasses, resourceClasses);          server.start();      }        private <T> T findAnnotationValueByClass(Class<T> annotationClass) {          for (Annotation annotation : getTestClass().getAnnotations()) {              if (annotation.annotationType().equals(annotationClass)) {                  return (T) annotation;              }          }          throw new IllegalStateException(String.format("Can't find %s on test class: %s", annotationClass, getTestClass()));      }        @Retention(RetentionPolicy.RUNTIME)      @Target(ElementType.TYPE)      public static @interface Resources {          public Class[] value();      }        @Retention(RetentionPolicy.RUNTIME)      @Target(ElementType.TYPE)      public static @interface Port {          public int value();      }    }
TJWSEmbeddedJaxrsServer是RESTEasy框架提供的嵌入式服务
  • 使用单个服务

MockShortMessage.java是Mock发送短信或邮件,CancelAutoOrderTest是测试类

import javax.ws.rs.Consumes;  import javax.ws.rs.POST;  import javax.ws.rs.Path;  import javax.ws.rs.Produces;  import javax.ws.rs.core.MediaType;  import javax.ws.rs.core.Response;    @Path("/mbp/mms/receiver/")  public class MockShortMessage {      @POST      @Consumes(MediaType.APPLICATION_XML)      @Produces(MediaType.APPLICATION_XML)      @Path("/shortmsg")      public Response mobileMessage(ShortMessageDto msg){          MessageRespDto respDto = new MessageRespDto();          return Response.ok().entity(respDto).build();      }        @POST      @Consumes(MediaType.APPLICATION_XML)      @Produces(MediaType.APPLICATION_XML)      @Path("/emailmsg")      public Response emailMessage(EmailMessageDto msg) {          MessageRespDto respDto = new MessageRespDto();          return Response.ok().entity(respDto).build();      }      }        import javax.ws.rs.core.Response;  import javax.ws.rs.core.Response.Status;      import junit.framework.Assert;    import org.junit.Ignore;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.springframework.beans.factory.annotation.Autowired;        @RunWith(ResteasyEmbededServer.class)  @ResteasyEmbededServer.Port(8007)  @ResteasyEmbededServer.Resources({MockShortMessage.class})  public class CancelAutoOrderTest extends DataPrepareFramework {     @Autowired   OrderResource orderResource;     @Autowired   OrderRepository orderRepository;     @Test   public void should_return_http_status_200_when_cancel_order() {    Assert.assertEquals("","");   }  }

  • 内嵌多个服务代码

import java.lang.annotation.Annotation;  import java.lang.annotation.ElementType;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;  import java.util.ArrayList;  import java.util.Collections;  import java.util.HashMap;  import java.util.List;  import java.util.Map;  import java.util.Map.Entry;    import org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer;  import org.junit.runner.notification.RunNotifier;  import org.junit.runners.model.InitializationError;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;    public class ResteasyMultiEmbededServer extends SpringJUnit4ClassRunner {        private List<TJWSEmbeddedJaxrsServer> servers = new ArrayList<TJWSEmbeddedJaxrsServer>();        public ResteasyMultiEmbededServer(Class<?> clazz) throws InitializationError {          super(clazz);      }        @Override      public void run(RunNotifier notifier) {          int[] ports = findAnnotationValueByClass(Ports.class).value();          Class[] resourceClasses = findAnnotationValueByClass(Resources.class).value();                    Map<Integer,List<Class>> maps = new HashMap<Integer,List<Class>>();                    for(int i=0;i<ports.length;i++){           int port = ports[i];           if(null==maps.get(port)){            maps.put(port,new ArrayList<Class>());           }           maps.get(port).add(resourceClasses[i]);          }          for(Entry<Integer,List<Class>> entry:maps.entrySet()){           startServer(new TJWSEmbeddedJaxrsServer(),entry.getKey(),entry.getValue().toArray(new Class[entry.getValue().size()]));          }          try {              super.run(notifier);          } finally {           for(TJWSEmbeddedJaxrsServer server:servers){               server.stop();           }          }      }        private void startServer(TJWSEmbeddedJaxrsServer server,int port, Class[] resourceClasses) {          server.setPort(port);          List<Class> actualResourceClasses = server.getDeployment().getActualResourceClasses();          Collections.addAll(actualResourceClasses, resourceClasses);          server.start();          servers.add(server);      }        private <T> T findAnnotationValueByClass(Class<T> annotationClass) {          for (Annotation annotation : getTestClass().getAnnotations()) {              if (annotation.annotationType().equals(annotationClass)) {                  return (T) annotation;              }          }          throw new IllegalStateException(String.format("Can't find %s on test class: %s", annotationClass, getTestClass()));      }        @Retention(RetentionPolicy.RUNTIME)      @Target(ElementType.TYPE)      public static @interface Resources {          public Class[] value();      }            @Retention(RetentionPolicy.RUNTIME)      @Target(ElementType.TYPE)      public static @interface Ports {    public int[] value();      }    }

  • 使用多个服务

这里mock了多个服务

@RunWith(ResteasyMultiEmbededServer.class)  @ResteasyMultiEmbededServer.Resources({MockCouponResource.class,MockEsbToBookingOrder.class,MockShortMessage.class})  @ResteasyMultiEmbededServer.Ports({8096,8011,8007})  public class BookingHotelServiceTest extends DataPrepareFramework{          @Test      public void should_save_coupon_when_booking_and_esb_return_success_given_coupon_and_booking_info() throws Exception{          Assert.assertEquals("","");      }    }