2017-04-19 1 views
1

실행 중에 JUnit4 테스트를 실행하고 Bytebuddy (버전 1.2.3)로 테스트를 가로 채어 테스트에서 어떤 메서드가 뮤 테이터인지 확인하려고합니다. 메소드 (기본 클래스의 변수 변경). 전체 프로세스는 정상적인 JUnit 테스트로 정상적으로 작동하지만 정확한 테스트를 실행하려고하지만 junit.framework.TestCase를 확장하면 프로세스가 충돌합니다. 오류를 다음과 같이 제한 할 수있었습니다. 디버그하려고하면 충돌을 일으키는 클래스 인 clazz="junit.framework.testcase" (Interceptor.java 참조)을 나타내는 많은 항목이 표시됩니다.junit.framework.TestCase가 Bytebuddy의 @Origin에 의해 차단되지 않도록 제외하는 방법

내 질문은 다음과 같습니다. TestCase 클래스를 가로채는 것을 어떻게 제외시킬 수 있습니까? 나는 다음과 같은 문장으로 그것을 시도 :

  1. ElementMatchers.not(ElementMatchers.namedIgnoreCase("junit.framework.testcase"))
  2. ElementMatchers.not(ElementMatchers.is(junit.framework.TestCase.class))
  3. 다음 코드로 ElementMatchers.not(ElementMatchers.nameContains("junit.framework"))

, 나는 콘솔 출력으로받을하려고 :

intercepted: tests.producttest 
running testSquarPrice 
intercepted: example.product 
finished testSquarPrice 

하지만, 결과는 항상 내 시도에도 다음 출력입니다. junit.framework.testcase을 제외하려면 다음은

intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: junit.framework.testcase 
intercepted: tests.producttest 
running testSquarPrice 
intercepted: example.product 
finished testSquarPrice 
intercepted: junit.framework.testcase 

내 코드입니다 :
Starter.java

import introspect.Agent; 

public class Starter { 
    public static void main(String[] args) { 
     Agent x = new Agent(); 
     x.run(); 
    } 
} 

에게 Agent.java

package introspect; 

import org.junit.runner.Request; 

import net.bytebuddy.dynamic.DynamicType.Builder; 

public class Agent { 

    public Agent() { 
    final Interceptor interceptor = new Interceptor(); 
    new AgentBuilder.Default() 
      .type(ElementMatchers.not(ElementMatchers.named("junit.framework.testcase")) 
        .and(ElementMatchers.nameStartsWithIgnoreCase("example") 
          .or(ElementMatchers.nameEndsWithIgnoreCase("test"))), 
        ElementMatchers.not(ElementMatchers.isBootstrapClassLoader())) 
      .transform(new AgentBuilder.Transformer() { 
       @Override 
       public Builder<?> transform(Builder<?> builder, TypeDescription arg1, ClassLoader arg2) { 
        return builder 
          .method(ElementMatchers.isPublic() 
            .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)))) 
          .intercept(MethodDelegation.to(interceptor).filter(ElementMatchers.named("intercept"))); 
       } 
      }).installOn(ByteBuddyAgent.install()); 
} 

    public void run() { 
     JUnitCore junit = new JUnitCore(); 

     Request request = Request.method(ProductTest.class, "testSquarPrice"); 
     junit.run(request); 
    } 
} 

Interceptor.java

package introspect; 

import java.lang.reflect.Method; 

import net.bytebuddy.implementation.bind.annotation.AllArguments; 
import net.bytebuddy.implementation.bind.annotation.Origin; 
import net.bytebuddy.implementation.bind.annotation.RuntimeType; 
import net.bytebuddy.implementation.bind.annotation.SuperCall; 
import net.bytebuddy.implementation.bind.annotation.This; 

public class Interceptor { 

    @RuntimeType 
    public Object intercept(@Origin Method m, @SuperCall Callable<?> zuper, @AllArguments Object[] args, 
      @This Object thiz) throws Exception { 

     // get the name of the intercepted class 
     String clazz = m.getDeclaringClass().getName().toLowerCase(); 
     System.out.println("intercepted: "+clazz); 

     return zuper.call(); 
    } 
} 

ProductTest.java

package tests; 

public class ProductTest extends TestCase{ 

    @Test 
    public void testSquarPrice() { 
     System.out.println("running testSquarPrice"); 

     Product p = new Product(); 

     int re = p.squarPrice(10); 

     assertTrue(re == 100); 

     System.out.println("finished testSquarPrice"); 
    } 
} 

Product.java ElementMatchers.not(ElementMatchers.is(junit.framework.TestCase.class))으로

package example; 

public class Product { 

    public int count, price, index; 

    public Product() { 
     index = 0; 
    } 

    public int squarPrice(int price) { 
     index++; 
     return price * price; 
    } 
} 

답변

1

, 당신은 단지 클래스 자체를 제외된다. 이 클래스에서 선언하고 다른 클래스에서 상속 한 메서드는 제외하지 않습니다.

method(ElementMatchers.isPublic() 
    .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)))) 
    .and(ElementMatchers.not(ElementMatchers.isDeclaredBy(TestCase.class)))) 

또는 같은 : 당신이 원하는 것은 아마 같은 것입니다 후자의 경우에

method(ElementMatchers.isPublic() 
    .and(ElementMatchers.isDeclaredBy(arg1))) 

만하지만, 선언의 방법을 가로채는 상속 된 메소드를 오버라이드 (override)하지 않습니다.

+0

고맙습니다. 첫 번째 솔루션은 완벽하게 작동했으며 두 번째 솔루션은 앞으로 도움이 될 수 있습니다. – Jacktraror

관련 문제