3

我正在编写一个 Rest API,我的自动化测试直接调用该类,而无需将其部署到服务器。例如,我正在测试这种方法:

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

我的测试正在检查逻辑是否有效并且它们通过了。但是这段代码有一个错误:我忘记在该参数上添加@QueryParam注释。view因此,此代码在测试时有效,但如果您尝试在已部署的应用程序上使用此资源,则该view参数将永远无法设置。

有很多方法可以解决这个问题,但我目前的偏好是以某种方式编写一个自动检查,如果一个方法有@Path注释,那么每个参数必须有 a @PathParam, a@QueryParam或任何其他有效的注释。

我更喜欢这个而不是新的端到端测试,因为我的其他测试已经涵盖了该逻辑的 95%。我只是不知道如何自动执行此检查。我正在使用 Maven 和 CXF(这意味着我正在使用 Spring)。我希望有一个可以配置为执行此操作的插件。


我刚刚意识到:有一个没有注释的参数是有效的。当你这样做时,jax-rs 将它设置为你传入的实体。我不确定如何处理这种情况。我可以创建自己的自定义注释@Payload并告诉人们使用它,但似乎有些不对劲。

4

1 回答 1

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 {
}
于 2015-04-15T23:14:29.170 回答