Exemple d’annotations personnalisées Java

Exemple d'annotations personnalisées Java

java-custom-annotation

Dans ce didacticiel, nous allons vous montrer comment créer deux annotations personnalisées -@Test et@TestInfo, pour simuler un cadre de test unitaire simple.

P.S This unit test example is inspired by this official Java annotation article.

1. Annotation @Test

Ce@interface indique à Java qu'il s'agit d'une annotation personnalisée. Plus tard, vous pouvez l'annoter au niveau de la méthode comme ceci@Test(enable=false).

Test.java

package com.example.test.core;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) //can use in method only.
public @interface Test {

    //should ignore this test?
    public boolean enabled() default true;

}

Note
Les déclarations de méthode ne doivent pas avoir de paramètres ni de clause throws. Les types de retour sont limités aux primitives, chaîne, classe, énumérations, annotations et tableaux des types précédents.

2. Annotation @TesterInfo

Ce@TesterInfo est appliqué au niveau de la classe, stockez les détails du testeur. Cela montre l'utilisation différente des types de retour - enum, array et string.

TesterInfo.java

package com.example.test.core;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) //on class level
public @interface TesterInfo {

    public enum Priority {
       LOW, MEDIUM, HIGH
    }

    Priority priority() default Priority.MEDIUM;

    String[] tags() default "";

    String createdBy() default "Mkyong";

    String lastModified() default "03/01/2014";

}

3. Exemple de test unitaire

Créez un exemple de test unitaire simple et annoté avec les nouvelles annotations personnalisées -@Test et@TesterInfo.

TestExample.java

package com.example.test;

import com.example.test.core.Test;
import com.example.test.core.TesterInfo;
import com.example.test.core.TesterInfo.Priority;

@TesterInfo(
    priority = Priority.HIGH,
    createdBy = "example.com",
    tags = {"sales","test" }
)
public class TestExample {

    @Test
    void testA() {
      if (true)
        throw new RuntimeException("This test always failed");
    }

    @Test(enabled = false)
    void testB() {
      if (false)
        throw new RuntimeException("This test always passed");
    }

    @Test(enabled = true)
    void testC() {
      if (10 > 1) {
        // do nothing, this test always passed.
      }
    }

}

4. Réflexion Java - Lire l'annotation

L'exemple ci-dessous vous montre comment utiliser les API de réflexion Java pour lire et traiter les annotations personnalisées.

RunTest.java

package com.example.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import com.example.test.core.Test;
import com.example.test.core.TesterInfo;

public class RunTest {

  public static void main(String[] args) throws Exception {

    System.out.println("Testing...");

    int passed = 0, failed = 0, count = 0, ignore = 0;

    Class obj = TestExample.class;

    // Process @TesterInfo
    if (obj.isAnnotationPresent(TesterInfo.class)) {

        Annotation annotation = obj.getAnnotation(TesterInfo.class);
        TesterInfo testerInfo = (TesterInfo) annotation;

        System.out.printf("%nPriority :%s", testerInfo.priority());
        System.out.printf("%nCreatedBy :%s", testerInfo.createdBy());
        System.out.printf("%nTags :");

        int tagLength = testerInfo.tags().length;
        for (String tag : testerInfo.tags()) {
            if (tagLength > 1) {
                System.out.print(tag + ", ");
            } else {
                System.out.print(tag);
            }
            tagLength--;
        }

        System.out.printf("%nLastModified :%s%n%n", testerInfo.lastModified());

    }

    // Process @Test
    for (Method method : obj.getDeclaredMethods()) {

        // if method is annotated with @Test
        if (method.isAnnotationPresent(Test.class)) {

            Annotation annotation = method.getAnnotation(Test.class);
            Test test = (Test) annotation;

            // if enabled = true (default)
            if (test.enabled()) {

              try {
                method.invoke(obj.newInstance());
                System.out.printf("%s - Test '%s' - passed %n", ++count, method.getName());
                passed++;
              } catch (Throwable ex) {
                System.out.printf("%s - Test '%s' - failed: %s %n", ++count, method.getName(), ex.getCause());
                failed++;
              }

            } else {
                System.out.printf("%s - Test '%s' - ignored%n", ++count, method.getName());
                ignore++;
            }

        }

    }
    System.out.printf("%nResult : Total : %d, Passed: %d, Failed %d, Ignore %d%n", count, passed, failed, ignore);

    }
}

Sortie

Testing...

Priority :HIGH
CreatedBy :example.com
Tags :sales, test
LastModified :03/01/2014

1 - Test 'testA' - failed: java.lang.RuntimeException: This test always failed
2 - Test 'testC' - passed
3 - Test 'testB' - ignored

Result : Total : 3, Passed: 1, Failed 1, Ignore 1

Terminé.