Как бы я написал автоматическую проверку, что каждый параметр имеет конкретную аннотацию?
Я пишу 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 {
}