java - Function to retrieve the top-most annotation from the call stack -
i define abstract base class defines generic reusable test cases want implement on , on again when testing various apis. idea define tests once, , can inherit generic test in order test definitions, , test code has implement specifics of how execute tests. way never miss test cases, not having re-invent wheel, nor making changes in dozens of places when think test case test.
in essence, i'm doing parameterized testing, parameters defined in base class. expected result defined in base class. however, there times when expected result needs overridden. example, ordinary string field might allow characters, whereas object name field may (or in case does) limit characters legal. example, string field allows "?" in value, name field not.
i'm trying figure out clean way of defining parameter once, in base class, , defining expected result once option of overriding in implementing class context requires it.
the problem have when override method, have replace implementation. can't replace portion of it. want replace expected outcome without overriding parameter portion. nor consider clean or desirable solution break every test 2 methods, 1 provides parameter , 1 defines expected behavior.
one option considering using annotations define expected results. can override annotation, , delegate implementation base class implementation. long base class uses annotation decide how behave, should work.
for example: (in pseudo-code, not real java)
abstract class foo { @fubar(true) void test1() { dosomething( param1 ) } @fubar(true) void test2() { dosomething( param2 ) } @fubar(false) void test3() { dosomething( param3 ) } boolean isfubar( void ) { ... } // generic annotation grabber void dosomething( p ) { if ( isfubar() ) dothis( p ) else dothat( p ); } // abstract methods defined in implementing class void dothis( p ); void dothat( p ); } class bar extends foo { // change expected result test2 @fubar(false) void test2() { super.test2(); } // define how execute tests void dothis(p) { ... } void dothat(p) { ... } } class baz extends bar { // changes semantics of test3, nothing else @fubar(true) void test3() { super.test3() } }
given hierarchy, foo.test1()
, bar.test1()
, , baz.test1()
same thing. whereas foo.test2()
1 thing, , bar.test2()
, baz.test2()
else. similarly, foo.test3()
, bar.test3()
1 thing, baz.test3()
different.
can use annotations accomplish behavior? if so, isfubar
like? i've yet see example of kind of reflection method name not known.
as side note, if there cleaner way accomplish intended behavior, i'd happy hear is.
to find earliest matching annotation in call stack, use function this:
static <t extends annotation> t seekannotation(class<t> annotationclass) { t annotation = null; try { (stacktraceelement ste : thread.currentthread().getstacktrace()) { t found = seekannotation(annotationclass, ste); if (found != null) { annotation = found; } } } catch (exception e) { // } return annotation; } static <t extends annotation> t seekannotation(class<t> annotationclass, stacktraceelement ste) { t annotation = null; try { class<?> claz = class.forname(ste.getclassname()); method method = claz.getdeclaredmethod(ste.getmethodname()); annotation = method.getannotation(annotationclass); } catch (exception e) { // } return annotation; }
there more work make robust, basic idea. method isfubar() like
boolean isfubar() { return seekannotation(fubar.class).value(); }
Comments
Post a Comment