16

我在问自己我应该在(单元)测试我的课程时走多远。例如,我有以下简单的类。

import javax.annotation.security.PermitAll;
import javax.ejb.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;


@Path(value = "ping")
@Singleton
@PermitAll
public class PingRestService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String pingMethod(){
        return "pong";
    }

}

我写了以下单元测试:

import static org.junit.Assert.*;
import java.lang.reflect.Method;
import javax.annotation.security.PermitAll;
import javax.ejb.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.junit.Test;


public class PingRestServiceTest {

    PingRestService prs = new PingRestService();

    @Test
    public void testClassAnnotations(){
        assertEquals(3, prs.getClass().getAnnotations().length);

        assertTrue(prs.getClass().isAnnotationPresent(PermitAll.class));
        assertTrue(prs.getClass().isAnnotationPresent(Singleton.class));
        assertTrue(prs.getClass().isAnnotationPresent(Path.class));

        assertEquals("ping", prs.getClass().getAnnotation(Path.class).value());

    }

    @Test
    public void testPingMethodAnnotations() throws SecurityException, NoSuchMethodException{

        Method method = prs.getClass().getDeclaredMethod("pingMethod");
        assertEquals(2, method.getAnnotations().length);

        assertTrue(method.isAnnotationPresent(GET.class));
        assertTrue(method.isAnnotationPresent(Produces.class));

        assertEquals(1, method.getAnnotation(Produces.class).value().length);
        assertEquals(MediaType.TEXT_PLAIN, method.getAnnotation(Produces.class).value()[0]);
    }

    @Test
    public void testPingMethod() {
        assertEquals("pong", prs.pingMethod());
    }

}

是否有意义?或者我应该只测试返回的字符串(“pong”,testPingMethod),跳过所有注释测试(testClassAnnotations,testPingMethodAnnotations)?

我认为一些注释是业务逻辑的一部分(例如 PermitAll),因此应该进行测试。

4

2 回答 2

5

大多数时候,人们测试的是代码的功能,而不是它的实现方式。这被称为Black Box Testing(见:http ://en.wikipedia.org/wiki/Black-box_testing)。在实施测试时,您应该问自己:“要测试的单元的可能输入值是什么?预期的结果是什么?” 现在在测试中,您使用输入值调用您的代码,并使用预期的结果检查结果,以确保您的代码按照您想要的方式运行。随着时间的推移,您可能会优化代码而不希望更改功能。那么你应该不需要改变你的测试。但是您可以重新运行它以确保它仍然以相同的方式运行。即使执行方式不同。或者,您可能会更改对您测试的功能有副作用的实施细节。同样在这种情况下,您不需要更改测试,而只需要重新运行它。在您的简单情况下,您没有输入和一个静态输出,因此您只需调用该方法并检查“pong”是否 被退回。但是经过测试的真实案例很少那么简单。

编辑:您可以看到@PermitAll配置的安全性和“@Path”配置为输入的 URL 路径,还可以按照“Boris the Spider”和“Avi”建议的方式在集成测试中测试它们。但其他注释是特定于实现的。

于 2013-06-23T14:35:37.190 回答
3

在我看来,这些注释是你的类的方面,而不是它的本质,它的真正目的,所以不应该进行单元测试。也许明天您将使用 Spring MVC 而不是 JAX-RS,但是您的类将具有相同的行为,因此单元测试应该是相同的

于 2013-06-23T14:40:18.897 回答