PrivateObject не находит свойство

У меня есть структура, которая выглядит примерно так:

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, указывающее, что свойство или метод не найдены. Но когда я отлаживаю и проверяю иерархию, все кажутся правильными, накладывая орфографию.

Благодарим вас за помощь.

Ответы

Ответ 1

Вам нужно установить аргумент PrivateType в базовый класс для доступа к закрытым членам на этом уровне.

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

Ответ 2

Не следует ли это "публичный класс AStub: A"?

Чтобы устранить недостающее исключение метода, просто скомпилируйте все (!) еще раз. Либо вы получите ошибку компилятора, указывающую на то, что неправильно, либо ошибка исчезнет.

Если он все еще не работает, проверьте, нет ли у вас нескольких копий сборок (включая GAC!) и смотрите в окне Deboug-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);
   ...
}