【问题标题】:PrivateObject does not find propertyPrivateObject 找不到属性
【发布时间】:2011-02-03 08:46:11
【问题描述】:

我的结构基本上是这样的:

abstract class A
{
   protected string Identificator { get; set; }

   private void DoSomething()
   {

       // ...

       DoSomethingSpecific();
   }

   protected abstract void DoSomethingSpecific();
}

由于复杂性,我需要对 DoSomething 方法进行单元测试,以确保它始终以相同的方式工作。这就是我创建以下存根的原因。

public class AStub : A
{
    protected override void DoSomethingSpecific()
    {
        // nothing to do
    }
}

我使用 PrivateObject 类来访问类 A 的方法和属性,以实例化类 AStub。这工作了一段时间,但由于某种原因,现在每当我尝试访问属性或方法时都会崩溃。

以下代码用于测试:

var sut = new CommonIodAdapterImpl();
var accessor = new PrivateObject(sut);

accessor.SetProperty("Identificator", "blablub");
accessor.Invoke("DoSomething", null);

// assert...

抛出的异常是 MissingMethodException,告诉我找不到属性或方法。但是当我调试和检查层次结构时,每个似乎都是正确的,包括拼写。

感谢您的帮助。

【问题讨论】:

  • 我们是否应该假设AStub 不是从A 继承的事实是问题中代码示例中的一个错字,并且它真的应该是public class AStub : A
  • 对不起,你是对的,我错过了一些东西......
  • 那么问题是您实际上没有从代码中的“A”继承还是您以其他方式解决了这个问题?
  • 在“测试代码”中,new CommonIodAdapterImpl()应该是new AStub()吗?

标签: c# .net unit-testing mstest


【解决方案1】:

您需要将 PrivateType 参数设置为您的基类以访问该级别的私有成员。

var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));

【讨论】:

    【解决方案2】:

    不应该是“公共类 AStub : A”吗?

    要解决缺少的方法异常,只需再次编译所有内容(!)。要么你得到一些编译器错误告诉你出了什么问题,要么错误就会消失。

    如果仍然无法正常工作,请检查您是否没有多个程序集副本(包括 GAC!),并在 Debug-Out-Window 中观察它是否从正确的路径加载程序集。

    【讨论】:

      【解决方案3】:

      我刚刚尝试了类似的方法,我认为这是因为该属性是受保护的而不是私有的。

      我在测试程序集中创建了自己的访问器

      public class AAccessor : A
      {
          // use this instead of Identificator
          public string IdentificatorAccessor 
          {
              get { return this.Identificator; }
              set { this.Identificator = value; }
          }
      
          // test this method in your unit test
          public void DoSomethingAccessor()
          {
              this.DoSomethingSpecific()
          }
      
          // need this to satisfy the abstract class
          protected override void DoSomethingSpecific()
          {
              // do nothing here
          }
      }
      

      【讨论】:

        【解决方案4】:
        public class BaseClass
        {
           private int _fieldToSet;
           ...
        }
        
        public class DerivedClass : BaseClass
        {
           ...
        }
        
        // Unit Test Code
        
        public void Test()
        {
           DerivedClass d = new DerivedClass();
           PrivateObject privObj = new PrivateObject(d, new PrivateType(typeof(BaseClass));
           privObj.SetFieldOrProperty("fieldToSet", 8675309);
           ...
        }
        

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
        • 基本上这段代码的关键是在 PrivateObject() 中声明类型。当您创建 PrivateObject() 时,它默认为您创建它的类的类型。因此,在上述情况下,PrivateObject() 只会创建 DeriverdClass() 类型的 PrivateObject,但是当您指定 PrivateObject 是 BaseClass 类型时,它现在知道创建 BaseClass 类型的 PrivateObject。
        猜你喜欢
        • 1970-01-01
        • 2018-05-06
        • 2021-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多