2010-07-08 2 views
5

내부 private 클래스의 PrivateType의 인스턴스를, 그러나 아주 작은 성공했다 방법 :내가 설정에 개인 내부 클래스에 대한 단위 테스트를 시도하고 있었다

PrivateType statKeyType = new PrivateType("Stats.Model", "Stats.Model.DailyStat.DailyStatKey"); 

: 나는이 코드를 시도

namespace Stats.Model 
{ 
    public class DailyStat 
    { 
    private class DailyStatKey // The one to test 
    { 
     private DateTime date; 
     public DateTime Date 
     { 
     get { return date; } 
     set { date = value.Date; } 
     } 

     public StatType Type { get; set; } 

     public override int GetHashCode() 
     { 
     return Date.Year * 1000000 + 
       Date.Month * 10000 + 
       Date.Day * 100 + 
       (int)Type; 
     } 

     public override bool Equals(object obj) 
     { 
     DailyStatKey otherKey = obj as DailyStatKey; 
     if (otherKey == null) 
      return false; 
     return (this.Date == otherKey.Date && this.StatType == otherKey.StatType); 
     } 
    } 
    } 
} 

을 뿐만 아니라

아무 소용이 없습니다.

어셈블리의 이름은 "Stats.Model"이며, 나에게 형 이름이 너무 올바른 보이지만, 난 그냥 예외 얻을 : 그래서 내가 뭘를

를 "형식을로드 할 수 없습니다 System.TypeLoadException을" 잘못된 ?

PrivateType은 내 생각에 반성을 기반으로하고 있으며, 네임 스페이스 바로 아래에 개인 클래스를 가질 수 없으므로이 시나리오를위한 것으로 생각됩니다.

편집 :

DailyStatKey의 전체 구현이 추가되었습니다. 테스트하고 싶은 것은 GetHashCode 메서드의 고유성입니다. 보시다시피 date + 유형을 단일 int에 맞추려고합니다.

+0

C#에서 "new SomeType (args)"은 리플렉션을 사용하지 않습니다. 대신 항상 생성자 호출이며 사용 가능한 생성자 중 하나를 호출합니다. 예제 코드에는 생성자가 없으므로 사용 가능한 유일한 생성자는 기본 생성자 (null 생성자 - 인수가없는 생성자)입니다. 클래스가 비공개이기 때문에 외부에서 호출 할 수 없습니다. 그래서 당신은 반성이 필요하다는 것이 옳습니다. – apollodude217

+0

관련 질문 : http : // stackoverflow.질문/3198912/use-reflection-or-a-property-unit-testing – apollodude217

+1

왜 생성자에 대한 부분을 언급하는지 잘 모르겠습니다. Reflection을 사용하는 PrivateType에 대한 의미는 개인 클래스/메소드에 액세스하는 데 RefType을 사용한다는 것입니다. (이것은 MSDN 페이지에서 분명히 드러납니다 : http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privatetype(VS.80).aspx ReflectionPermission이 필요하기 때문에. 관련 질문에 관해서는 그렇습니다. 개인 클래스는 테스트하지 말아야한다는 것을 알고 있습니다 만 내부적으로 만 사용되므로 GetHashCode가 항상 고유 한 값을 반환한다는 것이 중요하므로 테스트를하는 것이 좋습니다. – Steffen

답변

5

해결책을 찾을 자신 :

var parentType = typeof(DailyStat); 
var keyType = parentType.GetNestedType("DailyKeyStat", BindingFlags.NonPublic); 
//edited to use GetNestedType instead of just NestedType 

var privateKeyInstance = new PrivateObject(Activator.CreateInstance(keyType, true)); 

privateKeyInstance.SetProperty("Date", DateTime.Now); 
privateKeyInstance.SetProperty("Type", StatType.Foo); 

var hashCode = (int)privateKeyInstance.Invoke("GetHashCode", null); 
1

개인용이므로 인스턴스를 만들 수있는 유일한 클래스는 DailyStat입니다. 클래스를 만들려는 경우 프라이빗 리플렉션 (activator)을 사용하지 않는 것이 좋지만, 클래스를 만들려면 직접 선택해야합니다. 공용으로 충분히 캐스팅 할 수 없다면 직접 사용할 수는 없으므로 좋은 아이디어는 아닙니다. 유형 또는 인터페이스

편집 :

당신이이 비공개로 다음 효율적으로이 클래스를 테스트 야해 단위 테스트를 위해이 작업을 수행하려고하기 때문에. DailyStat의 공용 인터페이스를 통해서만 테스트 할 수 있습니다.

+0

흠,하지만 PrivateType은 Reflection AFAIK를 사용합니다. 나는 아직도 그것이 왜 문제인지 보지 못한다. PrivateType은 무엇을 위해 만들어 졌는가? 네임 스페이스에서 직접 개인 클래스를 가질 수는 없습니다. – Steffen

+0

외부 클래스 만 사용할 기능을 포함하려는 경우에 유용한 개인 내부 클래스 만 가질 수 있습니다. 내부에서 코딩 된 클래스 내에서만 새 PrivateType()을 사용할 수 있습니다. refelction은 관련이 없습니다. 그것이 개인 클래스를 instatitate하고 클래스 외부의 private 메소드를 호출하는 데 사용될 수 있기 때문에 나는 reflection을 언급했다. – aqwert

+0

그것은 외부 클래스 내에서 엄숙하게 사용되는 기능을 캡슐화하기위한 것이다. 그래서 그 부분은 괜찮습니다. PrivateType이 외부 클래스에서 작동하는지 확인합니다. – Steffen

-2

상위 클래스에 대해 공용 "GetDailyStatKey"메서드를 코딩 할 수 있습니다. 이제

public class DailyStat 
{ 
    private class DailyStatKey // The one to test 
    { 
    } 
    public DailyStatKey GetDailyStatKey() 
    { 
     return new DailyStatKey(); 
    } 
} 

당신은 쓸 수 있습니다 :

DailyStat v = new DailyStat(); 
var x = v.GetDailyStatKey(); 
+2

돌아 오는 유형이 호출 측에서는 보이지 않기 때문에 불가능합니다. 또한 원한다면 DailyStatKey를 public으로 설정할 수 있습니다. – Dykam

+0

다이캠 (Dykam)은 작동하지 않을 것이라고 말했고, 플러스 (public) 내부 클래스를 사용할 수도 있습니다. – Steffen

+0

public 인 내부 클래스에 인터페이스를 두어 세계에 보이는 것을 제어 할 수 있습니다. – aqwert

3

또한 직접뿐만 아니라 PrivateType를 사용할 수 있습니다

PrivateType statKeyType = new PrivateType("Stats.Model", "Stats.Model.DailyStat+DailyStatKey"); 

상자의 클래스가 있습니다 해당 형식과 다른 문자열 형식 네임 스페이스 (즉 Stats.Model.DailyStat.DailyStatKey)를 사용하므로 사용법이 명확하지 않습니다.

관련 문제