문제

이 질문은 테스트 사례를 작성하려고 시도하는 동안 발생합니다. Foo는 소스 액세스 권한이없는 프레임 워크 라이브러리 내 클래스입니다.

public class Foo{
  public final Object getX(){
  ...
  }
}

내 응용 프로그램이 될 것입니다

public class Bar extends Foo{
  public int process(){
    Object value = getX();
    ...
  }
}

다른 종속성으로 인해 FOO 객체를 만들 수 없으므로 단위 테스트 케이스는 비활성화 할 수 없습니다. 바르 테스트는 값이 null이므로 널 포인터를 던졌습니다.

public class BarTest extends TestCase{
  public testProcess(){
    Bar bar = new Bar();        
    int result = bar.process();
    ...
  }
}

반사 API를 사용하여 getx ()를 비 결절로 설정할 수있는 방법이 있습니까? 아니면 어떻게 테스트해야합니까?

도움이 되었습니까?

해결책

테스트에서 재정의 할 수있는 다른 방법을 만들 수 있습니다.

public class Bar extends Foo {
  protected Object doGetX() {
    return getX();
  }
  public int process(){
    Object value = doGetX();
    ...
  }
}

그런 다음 Bartest에서 Dogetx를 무시할 수 있습니다.

다른 팁

이것은 Google에서 "Final Method Java"의 주요 결과 중 하나였습니다. 나는 내 해결책을 떠날 것이라고 생각했다. 이 클래스는 예제 "베이글"클래스를 사용하여 간단한 솔루션을 보여주고 Javassist 라이브러리를 무료로 사용할 수 있습니다.

/**
 * This class shows how you can override a final method of a super class using the Javassist's bytecode toolkit
 * The library can be found here: http://jboss-javassist.github.io/javassist/
 * 
 * The basic idea is that you get the super class and reset the modifiers so the modifiers of the method don't include final.
 * Then you add in a new method to the sub class which overrides the now non final method of the super class.
 * 
 * The only "catch" is you have to do the class manipulation before any calls to the class happen in your code. So put the
 * manipulation as early in your code as you can otherwise you will get exceptions.
 */

package packagename;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;

/** 
 * A simple class to show how to use the library
 */
public class TestCt {

    /** 
     * The starting point for the application
     */
    public static void main(String[] args) {

        // in order for us to override the final method we must manipulate the class using the Javassist library.
        // we need to do this FIRST because once we initialize the class it will no longer be editable.
        try
        {
            // get the super class
            CtClass bagel = ClassPool.getDefault().get("packagename.TestCt$Bagel");

            // get the method you want to override
            CtMethod originalMethod = bagel.getDeclaredMethod("getDescription");

            // set the modifier. This will remove the 'final' modifier from the method.
            // If for whatever reason you needed more than one modifier just add them together
            originalMethod.setModifiers(Modifier.PUBLIC);

            // save the changes to the super class
            bagel.toClass();

            // get the subclass
            CtClass bagelsolver = ClassPool.getDefault().get("packagename.TestCt$BagelWithOptions");

            // create the method that will override the super class's method and include the options in the output
            CtMethod overrideMethod = CtNewMethod.make("public String getDescription() { return super.getDescription() + \" with \" + getOptions(); }", bagelsolver);

            // add the new method to the sub class
            bagelsolver.addMethod(overrideMethod);

            // save the changes to the sub class
            bagelsolver.toClass();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        // now that we have edited the classes with the new methods, we can create an instance and see if it worked

        // create a new instance of BagelWithOptions
        BagelWithOptions myBagel = new BagelWithOptions();

        // give it some options
        myBagel.setOptions("cheese, bacon and eggs");

        // print the description of the bagel to the console.
        // This should now use our new code when calling getDescription() which will include the options in the output.
        System.out.println("My bagel is: " + myBagel.getDescription());

        // The output should be:
        // **My bagel is: a plain bagel with cheese, bacon and eggs**
    }

    /**
     * A plain bagel class which has a final method which we want to override
     */
    public static class Bagel {

        /**
         * return a description for this bagel
         */
        public final String getDescription() {
            return "a plain bagel";
        }
    }

    /**
     * A sub class of bagel which adds some extra options for the bagel.
     */
    public static class BagelWithOptions extends Bagel {

        /**
         * A string that will contain any extra options for the bagel
         */
        String  options;

        /**
         * Initiate the bagel with no extra options
         */
        public BagelWithOptions() {
            options = "nothing else";
        }

        /**
         * Set the options for the bagel
         * @param options - a string with the new options for this bagel
         */
        public void setOptions(String options) {
            this.options = options;
        }

        /**
         * return the current options for this bagel
         */
        public String getOptions() {
            return options;
        }
    }
}

SEB는 정확하고, 귀하의 질문에 대한 답변을 얻기 위해, 기본 코드로 무언가를하지 않거나 (작동하지 않을 것이라고 확신합니다) 런타임시 클래스의 바이트 코드를 수정하고 클래스를 만들어냅니다. 런타임에서 메소드를 무시하면 메소드의 "최종"을 변경하는 방법을 볼 수 없습니다. 반성은 여기서 당신을 도울 것입니다.

다른 종속성으로 인해 단위 테스트 케이스가 FOO를 생성 할 수없는 경우, 이는 처음부터 장치 테스트를 제대로하지 않는다는 신호일 수 있습니다.

단위 테스트는 생산 코드가 실행되는 것과 동일한 상황에서 테스트하기위한 것이므로 테스트 내에서 동일한 생산 환경을 재현하는 것이 좋습니다. 그렇지 않으면 테스트가 완료되지 않습니다.

변수가 반환 된 경우 getX() 아니다 final 설명 된 기술을 사용할 수 있습니다 개인 방법을 테스트하는 가장 좋은 방법은 무엇입니까? 의 가치를 바꾸기 위해 private 변수 Reflection.

public class Bar extends Foo{
  public int process(){
    Object value = getX();
    return process2(value);
  }
  public int process2(Object value){
  ...
  }
}

public class BarTest extends TestCase{
  public testProcess(){
    Bar bar = new Bar();   
    Mockobj mo = new Mockobj();     
    int result = bar.process2(mo);
    ...
  }
}

내가 한 일은 결국 위였습니다. 약간 추악합니다 ... 제임스 솔루션은 이것보다 훨씬 낫습니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top