Статьи

Игра с JerseyTest (Джерси 2.5.1 и DI)

Я собираюсь попытаться объяснить тривиальный пример REST. Идея заключается в создании базовой схемы, чтобы начать играть с Джерси. Когда я начинаю использовать какую-то инфраструктуру, я обычно разрабатываю тестовую среду для быстрого провала, и это то, что я собираюсь сделать.

Следующий пример имеет следующие особенности:

  • Джерси 2.5.1
  • Внедрение зависимости
  • JUnit для тестирования

Классы:

  • Ресурс: он будет посещать HTTP-звонки.
  • Сервис: это интерфейс с двумя реализациями, Impl1 и Impl2.
  • ServiceProvider: он будет предоставлять соответствующую реализацию Service для каждого вызова запроса во время выполнения.
  • TestBinder: он устанавливает привязки в Ресурсе.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import static org.junit.Assert.assertEquals;
 
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
 
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
 
public class JerseyInjectionTest extends JerseyTest {
 
    private static final String EXPECTED_CONTENT = "any string :P";
 
    /**
     * Checks that the Resource uses Impl1.class
     */
    @Test
    public void invokeImpl1(){
        invoke(Impl1.class);
    }
 
    /**
     * Checks that the Resource uses Impl2.class
     */
    @Test
    public void invokeImpl2(){
        invoke(Impl2.class);
    }
 
    /**
     * Checks that Resource.anyContent has always the value of EXPECTED_CONTENT
     */
    @Test
    public void checkContent(){
        Response response = target("example/content").request().get();
        assertEquals(EXPECTED_CONTENT, response.readEntity(String.class));
    }
 
    private <T extends Service> void invoke(Class<T> service){
        final String serviceName = service.getName();
        Response response = target("example/"+serviceName).request().get();
        assertEquals(service.getName(), response.readEntity(String.class));
    }
 
    /**
     * Register the Resource and TestBinder in the Application
     */
    @Override
    protected Application configure() {
        return new ResourceConfig() {
            {
                register(new TestBinder());
                register(Resource.class);
            }
        };
    }
 
    @Path("/example")
    public static class Resource {
 
        @Inject
        Service service;
        @Inject
        String anyContent;
 
        /**
         * Returns the name of the Service's implementation
         */
        @GET
        @Path("/{serviceClass}")
        public Response getDynamicInvokedService() {
            return Response.ok(service.getClass().getName()).build();
        }
 
        /**
         * Returns always the value of anyContent
         */
        @GET
        @Path("/content")
        public Response getStaticContent() {
            return Response.ok(anyContent).build();
        }
 
    }
 
    /**
     * This class will help Resource to set the @Inject fields.
     */
    public static class TestBinder extends AbstractBinder{
 
        @Override
        protected void configure() {
            bindFactory(ServiceProvider.class).to(Service.class);
            bind(EXPECTED_CONTENT).to(String.class);
        }
 
    }
 
    /**
     * This class will instance a Services's implementation
     * per each time that the Resource is called.
     */
    @RequestScoped
    public static class ServiceProvider implements Factory<Service> {
 
        private final String serviceName;
 
        public ServiceProvider(@PathParam("serviceClass") String serviceName) {
            this.serviceName = serviceName;
        }
 
        @Override
        public void dispose(Service arg0) {}
 
        @Override
        public Service provide() {
            try {
                return (Service) Class.forName(serviceName).newInstance();
            } catch (Exception e) {
                return null;
            }
        }
 
    }
 
    /**
     * Dummy services
     */
    public static interface Service {}
    public static class Impl1 implements Service {}
    public static class Impl2 implements Service {}
 
}

Теперь мы можем легко попробовать новые функции.

Надеюсь, это поможет.

Ссылка: игра с JerseyTest (Jersey 2.5.1 и DI) от нашего партнера по JCG Серхио Молина в блоге TODOdev .