Can AspectJ replace "new X" with "new SubclassOfX" in third-party library code? -
i looking @ aspectj see if perhaps can use in our test suite.
we have rather large third party java communications library hardwired use own classes (which not implement interfaces) in turn mean need physical backend present , correctly configured able run tests.
i looking @ our options removing restriction. possibility create subclass of troublesome classes , ask aspectj replace "new x" "new oursubclassofx" when loading third party library, new aspectj , brief skimming of documentation not typical use case.
can aspectj this? configuration snippet be?
yes, possible. let assume have hard-wired class, possibly fetching database, , want mock via aspect:
package de.scrum_master.aop.app; public class hardwired { private int id; private string name; public hardwired(int id, string name) { this.id = id; this.name = name; } public void dosomething() { system.out.println("fetching values database"); } public int getsomething() { return 11; } @override public string tostring() { return "hardwired [id=" + id + ", name=" + name + "]"; } } then there little driver application using class (not interface):
package de.scrum_master.aop.app; public class application { public static void main(string[] args) { hardwired hw = new hardwired(999, "my object"); system.out.println(hw); hw.dosomething(); system.out.println(hw.getsomething()); } } the output follows:
hardwired [id=999, name=my object] fetching values database 11 now define derived mock class should replace original testing purposes:
package de.scrum_master.aop.mock; import de.scrum_master.aop.app.hardwired; public class hardwiredmock extends hardwired { public hardwiredmock(int id, string name) { super(id, name); } @override public void dosomething() { system.out.println("mocking database values"); } @override public int getsomething() { return 22; } @override public string tostring() { return "mocked: " + super.tostring(); } } and define aspect simple pointcut , advice replace original value during each constructor call:
package de.scrum_master.aop.aspect; import de.scrum_master.aop.app.hardwired; import de.scrum_master.aop.mock.hardwiredmock; public aspect mockinjector { hardwired around(int p1, string p2) : call(hardwired.new(int, string)) && args(p1, p2) { return new hardwiredmock(p1, p2); } } the output changes desired:
mocked: hardwired [id=999, name=my object] mocking database values 22 you once per class , constructor , fine. in order generalise approach need joinpoint properties and, depending on how far want go, maybe reflection, here pretty straightforward. enjoy!
Comments
Post a Comment