lappo
lappo

Reputation: 183

Unit testing annotations?

I'm asking myself how deep should I go in (unit) testing my classes. As example, I have following simple class .

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";
    }

}

I wrote following unit test:

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());
    }

}

does it make sense? Or should I only test the returning string ("pong", testPingMethod), skipping all annotations tests (testClassAnnotations,testPingMethodAnnotations) ?

I think some annotations are part of a business logic (e.g. PermitAll), and therefore should be tested.

Upvotes: 17

Views: 22231

Answers (2)

Sandro
Sandro

Reputation: 1835

Most of the time one tests the functionality of the code and not the way it is implemented. This is called Black Box Testing (see: http://en.wikipedia.org/wiki/Black-box_testing). When implementing a test you should ask yourself: "What are the possible input values of the unit to test and what are the expected results?" Now in the test you call your code with the input values and check the result with the expected one to make sure your code behaves the way you want it. Over time you might optimize the code without wanting to change the functionality. Then you should not need to change your test. But you can re-run it to make sure it still behaves the same way. Even if it is implemented differently. Or you might make change implementation details that have side effects to the functionality you tested. Also in this case you don't need to change the test but you just need to re-run it. In your simple case you have no input and one static output so you can just call the method and check if "pong" is returned. But real life cases that are tested are rarely that simple.

Edit: You can see the security that @PermitAll configures and the URL path that '@Path' configures as inputs and also test them in an integration test the way 'Boris the Spider' and 'Avi' suggested. But the other annotations are implementation specific.

Upvotes: 6

alex.net
alex.net

Reputation: 286

In my opinion those annotations are aspects of your class and not the essence of it, its real purpose, so shouldn't be unit tested. Maybe tomorrow you will use Spring MVC instead of JAX-RS, but your class would have the same behavior so the unit test should be the same

Upvotes: 4

Related Questions