Как бы я написал автоматическую проверку, что каждый параметр имеет конкретную аннотацию?

Я пишу Rest API, и мои автоматические тесты вызывают класс напрямую, без развертывания на сервере. В качестве примера я тестирую этот метод:

@GET
@Path("/{referenceId}")
@Produces("application/json")
public String findByReferenceId(@PathParam("referenceId") String referenceId,
                                String view) {

Мои тесты проверяют, что логика работает, и они проходят. Но этот код имеет ошибку: я забыл поставить @QueryParam аннотация на это view параметр. Таким образом, этот код работает при тестировании, но если вы попытаетесь использовать этот ресурс в развернутом приложении, view Параметр никогда не будет установлен.

Есть много способов, которыми я могу решить эту проблему, но в настоящее время я предпочитаю написать автоматическую проверку, что если метод имеет @Path аннотации, то каждый параметр должен иметь @PathParam, @QueryParam или любая другая действительная аннотация может быть там.

Я предпочитаю это перед новым сквозным тестом, потому что мои другие тесты уже покрывают 95% этой логики. Я просто не знаю, как автоматизировать эту проверку. Я использую Maven и CXF (что означает, что я использую Spring). Я надеюсь, что есть плагин, который можно настроить для этого.


Что-то, что я только что понял: допустимо иметь один параметр без аннотации. Когда вы делаете это, jax-rs устанавливает его для сущности, которую вы передаете. Я не уверен, как справиться с этим сценарием. Я мог бы создать свою собственную аннотацию под названием @Payload и скажи людям, чтобы они его использовали, но в этом что-то не так.

1 ответ

Вот мое решение. В итоге я решил создать @RawPayload аннотаций. В противном случае, я не могу знать, является ли недостающая аннотация преднамеренной или нет. Вот где я получил Reflections класс: https://code.google.com/p/reflections/

import org.junit.Test;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;

import javax.ws.rs.Path;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Set;

import static org.junit.Assert.assertTrue;

...

@Test
public void testAllParametersAreAnnotated() throws Exception {
    String message = "You are missing a jax-rs annotation on a method's parameter: ";
    Reflections reflections = new Reflections("package.for.my.services", new MethodAnnotationsScanner());
    Set<Method> resourceMethods = reflections.getMethodsAnnotatedWith(Path.class);
    assertTrue(resourceMethods.size() > 0);

    for (Method resourceMethod : resourceMethods) {
        for (int i = 0; i < resourceMethod.getGenericParameterTypes().length; i++) {
            Annotation[] annotations = resourceMethod.getParameterAnnotations()[i];
            boolean annotationExists = annotations.length > 0;
            assertTrue(message +
                            resourceMethod.getDeclaringClass().getCanonicalName() +
                            "#" +
                            resourceMethod.getName(),
                    annotationExists && containsJaxRsAnnotation(annotations));
        }
    }
}

private boolean containsJaxRsAnnotation(Annotation[] annotations) {
    for (Annotation annotation : annotations) {
        if (annotation instanceof RawPayload) {
            return true;
        }
        if (annotation.annotationType().getCanonicalName().startsWith("javax.ws.rs")) {
            return true;
        }
    }
    return false;
}

Вот моя аннотация:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * I'm creating this marker so that we can put it on raw payload params.  This is normally unnecessary,
 * but it lets me write a very useful automated test.
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface RawPayload {
}
Другие вопросы по тегам