如何实例化内部私有类的PrivateType

时间:2010-07-08 05:30:56

标签: c# unit-testing private-members

我试图为私人内部课程设置单元测试,但收效甚微:

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);
      }
    }
  }
}

我试过这段代码:

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

以及

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

无济于事。

程序集的名称是“Stats.Model”,对我来说类型名称看起来也是正确的,但我只是得到一个异常:“System.TypeLoadException:无法加载类型”

那么我做错了什么?

据我所知,PrivateType是基于反射的,我猜它几乎适用于这种情况,因为你不能在命名空间的正下方有一个私有类。

编辑:

添加了DailyStatKey的完整实现。我想测试的是我的GetHashCode方法的唯一性。如您所见,我尝试将日期+类型放入单个int中。

4 个答案:

答案 0 :(得分:6)

自己找到解决方案:

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 :(得分:5)

您也可以直接使用PrivateType:

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

嵌套类的字符串格式与其命名空间(Stats.Model.DailyStat.DailyStatKey)不同,因此用法并不明显。

答案 2 :(得分:1)

由于它是私有的,因此唯一可以创建实例的类是DailyStat本身。如果您想要创建课程,除非你做私人反映(激活器)将是你唯一的选择,虽然这不是一个好主意,因为你不能直接使用它,除非你能够将它投射到公众身上类型或界面

编辑:

由于您正在尝试对单元测试执行此操作,因此您实际上不应该测试此类,因为它是私有的。您只能通过DailyStat的任何公共接口进行测试。

答案 3 :(得分:-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();