如何编写每个参数都有特定注释的自动检查?

时间:2015-04-15 21:47:28

标签: java maven automation jax-rs cxfrs

我正在编写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 个答案:

答案 0 :(得分: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 {
}