KEMBAR78
Java custom annotations example | PDF
In this tutorial, we will show you how to create two custom annotations – @Test and @TestInfo , to simulate a simple
unit test framework.
P.S This unit test example is inspired by this official Java annotation article.
1. @Test Annotation
This @interface tells Java this is a custom annotation. Later, you can annotate it on method level like
this @Test(enable=false) .
Test.java
packagepackage comcom..mkyongmkyong..testtest..corecore;;
importimport javajava..langlang..annotationannotation..ElementTypeElementType;;
importimport javajava..langlang..annotationannotation..RetentionRetention;;
importimport javajava..langlang..annotationannotation..RetentionPolicyRetentionPolicy;;
importimport javajava..langlang..annotationannotation..TargetTarget;;
@Retention@Retention((RetentionPolicyRetentionPolicy..RUNTIMERUNTIME))
@Target@Target((ElementTypeElementType..METHODMETHOD)) //can use in method only.//can use in method only.
publicpublic @@interfaceinterface TestTest {{
//should ignore this test?//should ignore this test?
publicpublic booleanboolean enabledenabled(()) defaultdefault truetrue;;
}}
Note
Method declarations must not have any parameters or a throws clause. Return types are restricted to primitives,
String, Class, enums, annotations, and arrays of the preceding types.
2. @TesterInfo Annotation
This @TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum,
array and string.
TesterInfo.java
packagepackage comcom..mkyongmkyong..testtest..corecore;;
importimport javajava..langlang..annotationannotation..ElementTypeElementType;;
importimport javajava..langlang..annotationannotation..RetentionRetention;;
importimport javajava..langlang..annotationannotation..RetentionPolicyRetentionPolicy;;
importimport javajava..langlang..annotationannotation..TargetTarget;;
@Retention@Retention((RetentionPolicyRetentionPolicy..RUNTIMERUNTIME))
@Target@Target((ElementTypeElementType..TYPETYPE)) //on class level//on class level
publicpublic @@interfaceinterface TesterInfoTesterInfo {{
publicpublic enumenum PriorityPriority {{
LOWLOW,, MEDIUMMEDIUM,, HIGHHIGH
}}
PriorityPriority prioritypriority(()) defaultdefault PriorityPriority..MEDIUMMEDIUM;;
StringString[[]] tagstags(()) defaultdefault """";;
StringString createdBycreatedBy(()) defaultdefault "Mkyong""Mkyong";;
StringString lastModifiedlastModified(()) defaultdefault "03/01/2014""03/01/2014";;
}}
3. Unit Test Example
Create a simple unit test example, and annotated with the new custom annotations – @Test and @TesterInfo .
TestExample.java
packagepackage comcom..mkyongmkyong..testtest;;
importimport comcom..mkyongmkyong..testtest..corecore..TestTest;;
importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo;;
importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo..PriorityPriority;;
@TesterInfo@TesterInfo((
prioritypriority == PriorityPriority..HIGHHIGH,,
createdBycreatedBy == "mkyong.com""mkyong.com",,
tagstags == {{"sales""sales",,"test""test" }}
))
publicpublic classclass TestExampleTestExample {{
@Test@Test
voidvoid testAtestA(()) {{
ifif ((truetrue))
throwthrow newnew RuntimeExceptionRuntimeException(("This test always failed""This test always failed"));;
}}
@Test@Test((enabledenabled == falsefalse))
voidvoid testBtestB(()) {{
ifif ((falsefalse))
throwthrow newnew RuntimeExceptionRuntimeException(("This test always passed""This test always passed"));;
}}
@Test@Test((enabledenabled == truetrue))
voidvoid testCtestC(()) {{
ifif ((1010 >> 11)) {{
// do nothing, this test always passed.// do nothing, this test always passed.
}}
}}
}}
4. Java reflection – Read the Annotation
Below example show you how to use Java reflection APIs to read and process the custom annotations.
RunTest.java
packagepackage comcom..mkyongmkyong..testtest;;
p g y g ;
importimport javajava..langlang..annotationannotation..AnnotationAnnotation;;
importimport javajava..langlang..reflectreflect..MethodMethod;;
importimport comcom..mkyongmkyong..testtest..corecore..TestTest;;
importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo;;
publicpublic classclass RunTestRunTest {{
publicpublic staticstatic voidvoid mainmain((StringString[[]] argsargs)) throwsthrows ExceptionException {{
SystemSystem..outout..printlnprintln(("Testing...""Testing..."));;
intint passedpassed == 00,, failedfailed == 00,, countcount == 00,, ignoreignore == 00;;
ClassClass<<TestExampleTestExample>> objobj == TestExampleTestExample..classclass;;
// Process @TesterInfo// Process @TesterInfo
ifif ((objobj..isAnnotationPresentisAnnotationPresent((TesterInfoTesterInfo..classclass)))) {{
Annotation annotationAnnotation annotation == objobj..getAnnotationgetAnnotation((TesterInfoTesterInfo..classclass));;
TesterInfo testerInfoTesterInfo testerInfo == ((TesterInfoTesterInfo)) annotationannotation;;
SystemSystem..outout..printfprintf(("%nPriority :%s""%nPriority :%s",, testerInfotesterInfo..prioritypriority(())));;
SystemSystem..outout..printfprintf(("%nCreatedBy :%s""%nCreatedBy :%s",, testerInfotesterInfo..createdBycreatedBy(())));;
SystemSystem..outout..printfprintf(("%nTags :""%nTags :"));;
intint tagLengthtagLength == testerInfotesterInfo..tagstags(())..lengthlength;;
forfor ((String tagString tag :: testerInfotesterInfo..tagstags(()))) {{
ifif ((tagLengthtagLength >> 11)) {{
SystemSystem..outout..printprint((tagtag ++ ", "", "));;
}} elseelse {{
SystemSystem..outout..printprint((tagtag));;
}}
tagLengthtagLength----;;
}}
SystemSystem..outout..printfprintf(("%nLastModified :%s%n%n""%nLastModified :%s%n%n",, testerInfotesterInfo..lastModifiedlastModified(())));;
}}
// Process @Test// Process @Test
forfor ((Method methodMethod method :: objobj..getDeclaredMethodsgetDeclaredMethods(()))) {{
// if method is annotated with @Test// if method is annotated with @Test
ifif ((methodmethod..isAnnotationPresentisAnnotationPresent((TestTest..classclass)))) {{
Annotation annotationAnnotation annotation == methodmethod..getAnnotationgetAnnotation((TestTest..classclass));;
Test testTest test == ((TestTest)) annotationannotation;;
// if enabled = true (default)// if enabled = true (default)
ifif ((testtest..enabledenabled(()))) {{
trytry {{
methodmethod..invokeinvoke((objobj..newInstancenewInstance(())));;
SystemSystem..outout..printfprintf(("%s - Test '%s' - passed %n""%s - Test '%s' - passed %n",, ++++countcount,, methodmethod..getNamegetName(())));;
passedpassed++++;;
}} catchcatch ((ThrowableThrowable exex)) {{
SystemSystem..outout..printfprintf(("%s - Test '%s' - failed: %s %n""%s - Test '%s' - failed: %s %n",, ++++countcount,, methodmethod..getNamegetName(()),, exex..getCausegetCause(())));;
failedfailed++++;;
}}
}} elseelse {{
SystemSystem..outout..printfprintf(("%s - Test '%s' - ignored%n""%s - Test '%s' - ignored%n",, ++++countcount,, methodmethod..getNamegetName(())));;
ignoreignore++++;;
}}
}}
}}
}}
SystemSystem..outout..printfprintf(("%nResult : Total : %d, Passed: %d, Failed %d, Ignore %d%n""%nResult : Total : %d, Passed: %d, Failed %d, Ignore %d%n",, countcount,, passedpassed,, failedfailed,, ignoreignore));;
}}
}}
Output
TestingTesting......
Priority :HIGHPriority :HIGH
CreatedBy :mkyong.comCreatedBy :mkyong.com
Tags :sales,Tags :sales, testtest
LastModified :03/01/2014LastModified :03/01/2014
1 - Test1 - Test 'testA''testA' - failed: java.lang.RuntimeException: This- failed: java.lang.RuntimeException: This testtest always failedalways failed
2 - Test2 - Test 'testC''testC' - passed- passed
3 - Test3 - Test 'testB''testB' - ignored- ignored
ResultResult :: TotalTotal :: 3, Passed: 1, Failed 1, Ignore 13, Passed: 1, Failed 1, Ignore 1

Java custom annotations example

  • 1.
    In this tutorial,we will show you how to create two custom annotations – @Test and @TestInfo , to simulate a simple unit test framework. P.S This unit test example is inspired by this official Java annotation article. 1. @Test Annotation This @interface tells Java this is a custom annotation. Later, you can annotate it on method level like this @Test(enable=false) . Test.java packagepackage comcom..mkyongmkyong..testtest..corecore;; importimport javajava..langlang..annotationannotation..ElementTypeElementType;; importimport javajava..langlang..annotationannotation..RetentionRetention;; importimport javajava..langlang..annotationannotation..RetentionPolicyRetentionPolicy;; importimport javajava..langlang..annotationannotation..TargetTarget;; @Retention@Retention((RetentionPolicyRetentionPolicy..RUNTIMERUNTIME)) @Target@Target((ElementTypeElementType..METHODMETHOD)) //can use in method only.//can use in method only. publicpublic @@interfaceinterface TestTest {{ //should ignore this test?//should ignore this test? publicpublic booleanboolean enabledenabled(()) defaultdefault truetrue;; }} Note Method declarations must not have any parameters or a throws clause. Return types are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types. 2. @TesterInfo Annotation This @TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum, array and string. TesterInfo.java packagepackage comcom..mkyongmkyong..testtest..corecore;; importimport javajava..langlang..annotationannotation..ElementTypeElementType;; importimport javajava..langlang..annotationannotation..RetentionRetention;; importimport javajava..langlang..annotationannotation..RetentionPolicyRetentionPolicy;; importimport javajava..langlang..annotationannotation..TargetTarget;; @Retention@Retention((RetentionPolicyRetentionPolicy..RUNTIMERUNTIME)) @Target@Target((ElementTypeElementType..TYPETYPE)) //on class level//on class level publicpublic @@interfaceinterface TesterInfoTesterInfo {{
  • 2.
    publicpublic enumenum PriorityPriority{{ LOWLOW,, MEDIUMMEDIUM,, HIGHHIGH }} PriorityPriority prioritypriority(()) defaultdefault PriorityPriority..MEDIUMMEDIUM;; StringString[[]] tagstags(()) defaultdefault """";; StringString createdBycreatedBy(()) defaultdefault "Mkyong""Mkyong";; StringString lastModifiedlastModified(()) defaultdefault "03/01/2014""03/01/2014";; }} 3. Unit Test Example Create a simple unit test example, and annotated with the new custom annotations – @Test and @TesterInfo . TestExample.java packagepackage comcom..mkyongmkyong..testtest;; importimport comcom..mkyongmkyong..testtest..corecore..TestTest;; importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo;; importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo..PriorityPriority;; @TesterInfo@TesterInfo(( prioritypriority == PriorityPriority..HIGHHIGH,, createdBycreatedBy == "mkyong.com""mkyong.com",, tagstags == {{"sales""sales",,"test""test" }} )) publicpublic classclass TestExampleTestExample {{ @Test@Test voidvoid testAtestA(()) {{ ifif ((truetrue)) throwthrow newnew RuntimeExceptionRuntimeException(("This test always failed""This test always failed"));; }} @Test@Test((enabledenabled == falsefalse)) voidvoid testBtestB(()) {{ ifif ((falsefalse)) throwthrow newnew RuntimeExceptionRuntimeException(("This test always passed""This test always passed"));; }} @Test@Test((enabledenabled == truetrue)) voidvoid testCtestC(()) {{ ifif ((1010 >> 11)) {{ // do nothing, this test always passed.// do nothing, this test always passed. }} }} }} 4. Java reflection – Read the Annotation Below example show you how to use Java reflection APIs to read and process the custom annotations. RunTest.java packagepackage comcom..mkyongmkyong..testtest;;
  • 3.
    p g yg ; importimport javajava..langlang..annotationannotation..AnnotationAnnotation;; importimport javajava..langlang..reflectreflect..MethodMethod;; importimport comcom..mkyongmkyong..testtest..corecore..TestTest;; importimport comcom..mkyongmkyong..testtest..corecore..TesterInfoTesterInfo;; publicpublic classclass RunTestRunTest {{ publicpublic staticstatic voidvoid mainmain((StringString[[]] argsargs)) throwsthrows ExceptionException {{ SystemSystem..outout..printlnprintln(("Testing...""Testing..."));; intint passedpassed == 00,, failedfailed == 00,, countcount == 00,, ignoreignore == 00;; ClassClass<<TestExampleTestExample>> objobj == TestExampleTestExample..classclass;; // Process @TesterInfo// Process @TesterInfo ifif ((objobj..isAnnotationPresentisAnnotationPresent((TesterInfoTesterInfo..classclass)))) {{ Annotation annotationAnnotation annotation == objobj..getAnnotationgetAnnotation((TesterInfoTesterInfo..classclass));; TesterInfo testerInfoTesterInfo testerInfo == ((TesterInfoTesterInfo)) annotationannotation;; SystemSystem..outout..printfprintf(("%nPriority :%s""%nPriority :%s",, testerInfotesterInfo..prioritypriority(())));; SystemSystem..outout..printfprintf(("%nCreatedBy :%s""%nCreatedBy :%s",, testerInfotesterInfo..createdBycreatedBy(())));; SystemSystem..outout..printfprintf(("%nTags :""%nTags :"));; intint tagLengthtagLength == testerInfotesterInfo..tagstags(())..lengthlength;; forfor ((String tagString tag :: testerInfotesterInfo..tagstags(()))) {{ ifif ((tagLengthtagLength >> 11)) {{ SystemSystem..outout..printprint((tagtag ++ ", "", "));; }} elseelse {{ SystemSystem..outout..printprint((tagtag));; }} tagLengthtagLength----;; }} SystemSystem..outout..printfprintf(("%nLastModified :%s%n%n""%nLastModified :%s%n%n",, testerInfotesterInfo..lastModifiedlastModified(())));; }} // Process @Test// Process @Test forfor ((Method methodMethod method :: objobj..getDeclaredMethodsgetDeclaredMethods(()))) {{ // if method is annotated with @Test// if method is annotated with @Test ifif ((methodmethod..isAnnotationPresentisAnnotationPresent((TestTest..classclass)))) {{ Annotation annotationAnnotation annotation == methodmethod..getAnnotationgetAnnotation((TestTest..classclass));; Test testTest test == ((TestTest)) annotationannotation;; // if enabled = true (default)// if enabled = true (default) ifif ((testtest..enabledenabled(()))) {{ trytry {{ methodmethod..invokeinvoke((objobj..newInstancenewInstance(())));; SystemSystem..outout..printfprintf(("%s - Test '%s' - passed %n""%s - Test '%s' - passed %n",, ++++countcount,, methodmethod..getNamegetName(())));; passedpassed++++;; }} catchcatch ((ThrowableThrowable exex)) {{ SystemSystem..outout..printfprintf(("%s - Test '%s' - failed: %s %n""%s - Test '%s' - failed: %s %n",, ++++countcount,, methodmethod..getNamegetName(()),, exex..getCausegetCause(())));; failedfailed++++;; }} }} elseelse {{ SystemSystem..outout..printfprintf(("%s - Test '%s' - ignored%n""%s - Test '%s' - ignored%n",, ++++countcount,, methodmethod..getNamegetName(())));; ignoreignore++++;; }}
  • 4.
    }} }} }} SystemSystem..outout..printfprintf(("%nResult : Total: %d, Passed: %d, Failed %d, Ignore %d%n""%nResult : Total : %d, Passed: %d, Failed %d, Ignore %d%n",, countcount,, passedpassed,, failedfailed,, ignoreignore));; }} }} Output TestingTesting...... Priority :HIGHPriority :HIGH CreatedBy :mkyong.comCreatedBy :mkyong.com Tags :sales,Tags :sales, testtest LastModified :03/01/2014LastModified :03/01/2014 1 - Test1 - Test 'testA''testA' - failed: java.lang.RuntimeException: This- failed: java.lang.RuntimeException: This testtest always failedalways failed 2 - Test2 - Test 'testC''testC' - passed- passed 3 - Test3 - Test 'testB''testB' - ignored- ignored ResultResult :: TotalTotal :: 3, Passed: 1, Failed 1, Ignore 13, Passed: 1, Failed 1, Ignore 1