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.
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 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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With