MessageBodyProviderNotFoundException выбрасывается в JerseyTest при использовании GSON

Я использую Джерси и решил использовать GSON вместо Moxy для обработки JSON (мне не нравился тот факт, что Moxy требуются сеттеры).

До сих пор все работает нормально, кроме одного очень раздражающего вопроса в моем JerseyTest подклассы: обычай GsonProvider не распознается, если явно не зарегистрировано для каждого вызова. Тем не менее, он распознается, если я разверну приложение в Tomcat.

мой ResourceConfig:

@ApplicationPath("")
public class MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        register(GsonProvider.class);

        register(SomeResource.class);
    }
}

Реализация GsonProvider (хотя я не думаю, что это связано с проблемой, с которой я сталкиваюсь):

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class GsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> {

    private final Gson mGson;

    public GsonProvider() {
        mGson = new GsonBuilder().create();
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType,
                              Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
                      MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
                      InputStream entityStream) throws IOException, WebApplicationException {

        InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8");
        try {
            return mGson.fromJson(reader, type);
        } finally {
            reader.close();
        }
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
                               Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public long getSize(T t, Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations,
                        MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
                        OutputStream entityStream) throws IOException, WebApplicationException {

        PrintWriter printWriter = new PrintWriter(entityStream);
        try {
            String json = mGson.toJson(t);
            printWriter.write(json);
            printWriter.flush();
        } finally {
            printWriter.close();
        }
    }
}

Результаты этого теста в MessageBodyProviderNotFoundException:

public class SomeResourceTest extends JerseyTest {
    @Override
    public Application configure() {
        return new MyResourceConfig();
    }

    @Test
    public void someApi_200Returned() throws Exception {
        // Arrange
        // Act
        SomeResponse response =
                target("/somepath")
                        .request()
                        .post(Entity.json(""), SomeResponse.class);
        // Assert
        assertThat(response.getStatus(), is(200));
    }
}

Для решения этой проблемы я регистрируюсь GsonProvider по запросу. Следующее изменение делает тестовый прохождение:

public class SomeResourceTest extends JerseyTest {
    @Override
    public Application configure() {
        return new MyResourceConfig();
    }

    @Test
    public void someApi_200Returned() throws Exception {
        // Arrange
        // Act
        SomeResponse response =
                target("/somepath")
                        .register(GsonProvider.class)
                        .request()
                        .post(Entity.json(""), SomeResponse.class);
        // Assert
        assertThat(response.getStatus(), is(200));
    }
}

Итак, регистрация GsonProvider в MyResourceConfig хорошо для развертывания, но JerseyTest требует дополнительной регистрации за запрос.

Хотя я могу жить с этим, это раздражает, отнимает много времени и будет трудно общаться с другими членами команды. Любое решение для этой проблемы?

1 ответ

Решение

Вы не показали трассировку стека, но я уверен, что если вы внимательно посмотрите на нее, это покажет, что это на самом деле ошибка на стороне клиента. Вам нужно также зарегистрировать провайдера gson на клиенте, поскольку вы пытаетесь десериализовать ответ JSON для POJO.

@Override
public void configureClient(ClientConfig config) {
    config.register(GsonProvider.class)
}

configureClient метод является методом в JerseyTest что вы можете переопределить.

Другие вопросы по тегам