2014-09-11 10 views
0

Unit Test에서 전용 멤버에 액세스하려면 어떻게합니까? PrivateObject를 사용하려고하지만 과부하 생성자가 여기에 있고 _inkContainerValue에 대한 오류가 발생합니다. 수업의 대상을 사용하지 않고 비회원에게 접근 할 수 있습니까? 위의 코드과부하 생성자가있는 클래스의 전용 멤버 C# Unit Test

public class Pen 
    { 

    private int _inkContainerValue = 1000; 

    #region Constructors 

    public Pen(int inkContainerValue) 
    { 
     this._inkContainerValue = inkContainerValue; 
    } 

    #endregion 
    } 

}

+9

일반적으로 비공개 회원을 테스트해서는 안됩니다. 테스트가 그들에게 접근 할 필요가 있다면 디자인을 재고해야합니다. 그 사치품이 없을 때, 나는 보통 반성을 사용합니다. – phoog

+0

리플렉션을 사용하는 방법을 알고 있지만 그 이유는 생성자 오버로드가 여기에 있기 때문입니다. –

+2

필드 및 생성자 오버로드에 액세스하는 것과 어떻게 관련이 있습니까? –

답변

0
PrivateObject pObj = new PrivateObject(typeof(Pen)); 
int privateInkContainerValue = (int)pObj.GetField("_inkContainerValue"); 

시도는 단위 테스트에 PrivateObject 클래스를 통해 _inkContainerValue 필드의 값을 얻을 수 있습니다.

// Following is overloaded version to pass value to actual Pen class's constructor. 
PrivateObject pObj = new PrivateObject(typeof(Pen), new object[]{12}); 
int privateInkContainerValue = (int)pObj.GetField("_inkContainerValue"); 

저는 현재 편집자가 없습니다. 구문이 이상적으로 작동해야합니다.

+0

첫 번째 코드는 사용했지만 p0bj에 오류가 발생했습니다. privateInkContainerValue의 값이 12이기 때문에 두 번째가 올바르게 작동하지 않습니다 –

+0

한번보세요. –

+0

두 번째 작업은 12가 첫 번째 생성자에 값으로 전달되기 때문입니다. 12를 자신의 변수/값으로 바꾸면 결과를 테스트 할 수 있습니다. –

0

클래스 개체를 사용하지 않고 비공개 멤버에 액세스 할 수 있습니까?

아니요. 해당 개체의 데이터를 가져 오려면 개체의 인스턴스가 있어야합니다.

위법은 아닙니다.하지만 생성자 오버로딩으로 인해 Reflection을 사용하는 것에 대한 주저는 의심스러워합니다. 인스턴스가 있거나 리플리렉션을 만들지 않으면 리플렉션을 사용하지 못하게해야합니다.

다음은 Reflection을 사용하여 _ink에서 값을 가져 오는 예제입니다. 또한 생성자를 사용하지 않고 인스턴스를 가져 오는 방법을 보여줍니다. 그러나 은 없습니다.은 초기화됩니다. 코드에서 볼 때 _ink0이 아니고 1000이 아닙니다. FormatterServices 클래스를 사용하기 위해

public class Pen 
{ 
    int _ink = 1000; 

    public Pen(int ink) 
    { 
     _ink = ink; 
    } 
} 

void Test() 
{ 
    //Create the object and check constructor set the value 
    var pen = new Pen(5); 
    var field = pen.GetType().GetField("_ink", BindingFlags.NonPublic|BindingFlags.Instance); 

    // This should pass. 
    Debug.Assert((int)field.GetValue(pen) == 5); 

    // Create the pen without using constructor. 
    // No matter what, nothing is initialized meaning _ink is 0 and not 1000. 
    // Hence, uninitialized. 
    var uninitializedPen = (Pen)FormatterServices.GetUninitializedObject(typeof(Pen)); 
    field = uninitializedPen.GetType().GetField("_ink", BindingFlags.NonPublic|BindingFlags.Instance); 

    //This will fail. 
    Debug.Assert((int)field.GetValue(uninitializedPen) == 1000); 
} 

, 당신은 System.Runtime.Serialization 네임 스페이스를 가져와야합니다.

+0

@JonJin 질문에 입력 한 원래 코드는 무엇입니까? 내가 볼 수있는 것에는 아무 문제가 없습니다. 편집 : 오 하느님 ..... – TyCobb

+0

죄송합니다 :) 여기 있습니다 http://pastie.org/9546814 –

+0

인스턴스를 만들었지 만 값을 얻으려고하면 "NullReference"예외가 발생합니다 –