Then TestRule, a built in Junit interface which brought my attention, is easy and powerful to customize your test code behaviors.
TestRule
As I understand, the TestRule is an interface which developer can inject into test classes, which is similar to the aspectj Around point cut.
The code below implements TestRule and return an inner class as CustomStatement that injects some code before and after the testing code (base.evaluate())
public class SimpleTestRule implements TestRule{ public Statement apply(Statement base, Description description) { return new CustomStatement(base); } private class CustomStatement extends Statement{ private Statement base; public CustomStatement(Statement base) { this.base = base; } @Override public void evaluate() throws Throwable { //Before test execution System.out.println("Before Test Running"); //Test execution base.evaluate(); //After test execution System.out.println("After Test Running"); } } }
Use the above Custom Test Rule
public class SimpleTestRuleTest { @Rule public TestRule rule = new SimpleTestRule(); @Test public void test(){ System.out.println("My test is running"); } }Code execution Result:
Before Test Running
My test is running
After Test Running
Multiple User TestRule
After understanding the above simple test rule, we can start create a more complicate rule to support multiple threading of tests.
The following code wrapped the test execution code (base.evaluate()) into an independent thread.
public class MultiUserTestRule implements TestRule{ private final int numOfUsers; private final ExecutorService executor; public MultiUserTestRule(int poolSize, int numOfUsers){ this.numOfUsers = numOfUsers; executor = Executors.newFixedThreadPool(poolSize); } public Statement apply(Statement base, Description description) { return new CustomStatement(base); } private class CustomStatement extends Statement{ private Statement base; public CustomStatement(Statement base) { this.base = base; } @Override public void evaluate() throws Throwable { for(int i=0; i< numOfUsers; i++){ executor.execute(new Thread(new Runnable() { public void run() { try { base.evaluate(); } catch (Throwable e) { throw new IllegalArgumentException(e); } } })); } } } }Use the above test Rule
public class MultiUserTestRuleTest { /** * The thread pool size is 10 * There are 5 users run the tests */ @Rule public TestRule rule = new MultiUserTestRule(10, 5); @Test public void test(){ System.out.println(Thread.currentThread().getName() + " is running the test"); } }The above test case is trying to print out each current thread name for demo purpose.
The result is:
pool-1-thread-1 is running the test
pool-1-thread-4 is running the test
pool-1-thread-5 is running the test
pool-1-thread-2 is running the test
pool-1-thread-3 is running the test
All the above code can be found here: https://github.com/datianshi/multiuser-junit
No comments:
Post a Comment