4

For example, I have thousands of method like:

AA() {
    ...
}  
BB() {
    ...
}  
CC() {
    ...
}  
etc ...

Now I want to call a method printCurrentMethodName() on the beginning of each method. That means,

AA() {
    printCurrentMethodName();
    ...
}  
BB() {
    printCurrentMethodName();
    ...
}  
CC() {
    printCurrentMethodName();
    ...
}  
etc ...

Including printCurrentMethodName() on the start of thousands of method is time consuming.

Is there any way that I can call printCurrentMethodName() on the beginning of each methods without repeating it in those thousands of method?

(I can't use something like @Before or @BeforeMethod annotation, because it will call printCurrentMethodName() before entering AA() and so it will not print the method name as expected)

davidgiga1993
  • 2,695
  • 18
  • 30
Shahid
  • 2,288
  • 1
  • 14
  • 24

5 Answers5

3

You can use java.lang.reflect.InvocationHandler for this purpose.

Before any of the methods inside your class is called (AA,BB,CC etc.) the invoke method of your InvocationHandler is called. Inside the invoke method you have access to the actual method that was called and you can add additional logic, like printing the name the called method, to be executed before or after the actual method is called.

Code example:

public class PrintClassName {
    public static void main(String[] a) {
        Service srv = (Service) Proxy.newProxyInstance(
                PrintClassName.class.getClassLoader(),
                new Class<?>[]{Service.class},
                new PrintingMethodNameHandler(new ServiceImpl())
            );

        srv.doNothing();
    }
}

interface Service {
    void doNothing();
}

class ServiceImpl implements Service {
    public void doNothing() { }
}

class PrintingMethodNameHandler implements InvocationHandler {
    private Service service;

    public PrintingMethodNameHandler(final Service service) {
        this.service = service;
    }

    @Override
    public Object invoke(final Object proxy, final Method method,
            final Object[] args) throws Throwable {
        System.out.println(method.getName());
        return method.invoke(service, args);
    }
}
Adam Siemion
  • 15,569
  • 7
  • 58
  • 92
3

If you only want to print the names of the test methods then you could create a JUnit rule that is similar to the TestName rule

public class PrintTestName extends TestWatcher {
  @Override
  protected void starting(Description d) {
      System.out.println(d.getMethodName());
  }
}

and use it in your test

public class YourTest {
  @Rule
  public final PrintTestName printTestName = new PrintTestName();

  @Test
  public AA() {
    ...
  }

  ...
Stefan Birkner
  • 24,059
  • 12
  • 57
  • 72
1

You could use a regex to insert this call on every function.

Replace (\w+\(\w*\)\s*\{) with $1\nprintCurrentMethodName();

davidgiga1993
  • 2,695
  • 18
  • 30
0

How about using AspectJ annotations.

For ex-

Common AspectJ annotations : 1.@Before – Run before the method execution

2.@After – Run after the method returned a result

3.@AfterReturning – Run after the method returned a result, intercept the returned result as well.

4.@AfterThrowing – Run after the method throws an exception

5.@Around – Run around the method execution, combine all three advices above.

This may solve your problem . You can use this to call a method when it is returned,

You may follow this tutorial.

RajSharma
  • 1,941
  • 3
  • 21
  • 34
  • 1
    @CodeProcessor He said that he don't want to use Before or BeforeMethod annotation – Naveen Ramawat Jul 06 '15 at 07:58
  • I know but @AfterReturning may solve his problem. He just want to avoid writing it again and again. In order to do that he can use .@AfterReturning. I have written in my answer also. – RajSharma Jul 06 '15 at 08:01
  • 2
    This answer might actually talk about the best solution (aspect oriented programming), but this answer is currently useless: OP is clearly aware of these techniques, but doesn't know how to apply them to a large number of methods and still be able to get the method name. Since you seem to know AspectJ well, could you please [edit] your answer to include a small code snippet to illustrate its usage? – amon Jul 06 '15 at 08:25
-1

It is simple, Put this line in your method.

System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName());
Naveen Ramawat
  • 1,425
  • 1
  • 15
  • 27
  • 2
    he wants to avoid writting againa and again. he wnats to call that metod after enterting on other methods. – RajSharma Jul 06 '15 at 07:00