1

I need to execute some code before the @Before method of each unit test is executed. The problem is that I also need to know which test (the name is sufficient) will be executed afterwards.

I can either use AspectJ or Java Agents with bytecode manipulation to achieve this. Also the solution should work for tests where there is no @Before annotation present.

Any ideas?

EDIT: I can't modify the unit tests themselves, as I'm developing a framework for executing tests of other projects

skappler
  • 722
  • 1
  • 10
  • 26

2 Answers2

0

You might want to look into the TestName rule in JUnit: http://junit.org/junit4/javadoc/4.12/org/junit/rules/TestName.html

About the ordering, a solution could be to define a super class for your tests and put a @Before in there, as @Before methods in super classes are run before those in sub classes.

Thomas Kåsene
  • 5,301
  • 3
  • 18
  • 30
  • I forgot to mention that I can't modify the unit tests themselves. Will edit the question – skappler Oct 01 '16 at 09:05
  • Maybe you can implement your own JUnit Runner: http://junit.sourceforge.net/javadoc/org/junit/runner/Runner.html I'm not sure how viable this option is though, as tests might want to use MockitoJUnitRunner, for instance. – Thomas Kåsene Oct 01 '16 at 09:11
  • Thought about this too, but then I would need to dynamically replace the normal one with instrumentation or AspectJ, and I haven't looked into this. I'm not allowed to make any static changes to the projects, so I can't use my own modified JUnit version – skappler Oct 01 '16 at 09:13
0

If you want to write a Java agent and you are not bound to Javassist or AspectJ, have a look at Byte Buddy for doing so. You can add the code in the MyAdvice class to any method annotated with @Test given that the type name ends with Test (as an example) by:

public class MyAgent {
  public static void premain(String arg, Instrumentation inst) {
    new AgentBuilder.Default()
    .type(nameEndsWith("Test"))
    .transform((type, cl, builder) -> builder.visit(Advice
        .to(MyAdvice.class)
        .on(isAnnotatedWith(Test.class)))
    .installOn(instrumentation);
  }
}

class MyAdvice {
  @Advice.OnMethodEnter
  static void enter() {
    System.out.println("foo");
  }
}

Just bundle the above code to a Javaagent with the proper manifest code and register it before running. If you are running on a JDK, you can also attach the agent programmatically using the byte-buddy-agent project.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192