Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 681
lappo Avatar asked Jun 23 '13 14:06

lappo


People also ask

Which annotation is used for unit testing?

A JUnit test is a method contained in a class which is only used for testing. This is called a Test class. To define that a certain method is a test method, annotate it with the @Test annotation. This method executes the code under test.

What are testing annotations?

What are TestNG Annotations? TestNG Annotations are used to control the next method to be executed in the test script. TestNG annotations are defined before every method in the test code. In case any method is not prefixed with annotations, it will be ignored and not be executed as part of the test code.

What are annotations in JUnit?

JUnit Annotations is a special form of syntactic meta-data that can be added to Java source code for better code readability and structure. Variables, parameters, packages, methods and classes can be annotated. Annotations were introduced in Junit4, which makes Java code more readable and simple.

How many annotations are there in JUnit?

As a result i am aware of few annotations which are used in JUnit :- @Test , @Before , @After , @Ignore , @BeforeClass , @AfterClass , @Runwith(Suite. class) , @SuiteClasses({}) , @Parameters , @RunWith(Parameterized. class) and @Rule . I am sure there are more annotations which are used in JUnit.


2 Answers

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.

like image 79
Sandro Avatar answered Oct 17 '22 03:10

Sandro


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

like image 44
alex.net Avatar answered Oct 17 '22 01:10

alex.net