Ответ 1
Вам нужно установить аргумент PrivateType в базовый класс для доступа к закрытым членам на этом уровне.
var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));
У меня есть структура, которая выглядит примерно так:
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, указывающее, что свойство или метод не найдены. Но когда я отлаживаю и проверяю иерархию, все кажутся правильными, накладывая орфографию.
Благодарим вас за помощь.
Вам нужно установить аргумент PrivateType в базовый класс для доступа к закрытым членам на этом уровне.
var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));
Не следует ли это "публичный класс AStub: A"?
Чтобы устранить недостающее исключение метода, просто скомпилируйте все (!) еще раз. Либо вы получите ошибку компилятора, указывающую на то, что неправильно, либо ошибка исчезнет.
Если он все еще не работает, проверьте, нет ли у вас нескольких копий сборок (включая GAC!) и смотрите в окне Deboug-Out-Window, если он загружает сборки с правильного пути.
Я просто попробовал что-то подобное, я его осмелился, потому что свойство защищено, а не частное.
Я создал свой собственный аксессуар в своей тестовой сборке
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
}
}
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);
...
}