Как написать спецификации с MSpec для кода, который изменяет Thread.CurrentPrincipal?

Я конвертировал некоторые старые спецификации в MSpec (использовал NUnit/SpecUnit). Спецификации предназначены для модели представления, и рассматриваемая модель представления выполняет некоторую пользовательскую проверку безопасности. У нас есть вспомогательный метод в наших спецификациях, который настроит поддельные учетные данные безопасности для Thread.CurrentPrincipal. Это хорошо работало в старых модульных тестах, но не работает в MSpec. В частности, я получаю это исключение:

"System.Runtime.Serialization.SerializationException: тип не разрешен для члена"

Это происходит, когда часть SUT пытается прочитать файл конфигурации приложения. Если я закомментирую строку, которая устанавливает CurrentPrincipal (или просто вызову его после части, которая проверяет файл конфигурации), ошибка исчезнет, ​​но тесты не пройдут из-за отсутствия учетных данных.

Точно так же, если я установлю для CurrentPrincipal значение null, ошибка исчезнет, ​​но снова тесты не пройдутся, поскольку учетные данные не установлены. Я погуглил это и нашел несколько сообщений о том, что сериал можно настраивать, когда пользователь пересекает границы AppDomain (обычно это касается веб-приложений). В нашем случае это не веб-приложение, и я не пересекаю никакие домены приложений. Наш главный объект также сериализуем.

Я загрузил исходный код MSpec и обнаружил, что ConsoleRunner вызывает класс с именем AppDomainRunner. Я не отлаживал его, но похоже, что он запускает спецификации в разных доменах приложений.

Так у кого-нибудь есть идеи, как мне это преодолеть? Мне очень нравится MSpec, и я хотел бы использовать его исключительно. Но я должен быть в состоянии предоставить поддельные учетные данные безопасности во время выполнения тестов.

Вот класс спецификаций:

[Subject(typeof(CountryPickerViewModel))]
public class When_the_user_makes_a_selection : PickerViewModelSpecsBase
{
    protected static CountryPickerViewModel picker;

    Establish context = () =>
    {
        SetupFakeSecurityCredentials();
        CreateFactoryStubs();

        StubLookupServicer<ICountryLookupServicer>()
            .WithData(BuildActiveItems(new [] { "USA", "UK" }));

        picker = new CountryPickerViewModel(ViewFactory, ViewModelFactory, 
                                BusinessLogicFactory, CacheFactory);

    };

    Because of = () =>
        picker.SelectedItem = picker.Items[0];

    Behaves_like<Picker_that_has_a_selected_item> a_picker_with_a_selection;
}

У нас есть несколько таких моделей представления "сборщик", каждая из которых демонстрирует некоторое общее поведение. Поэтому я использую функцию поведения в MSpec. Этот конкретный класс имитирует выбор пользователем чего-либо из элемента управления (WPF), который связан с этой виртуальной машиной. Метод SetupFakeSecurityCredentials() просто устанавливает для Thread.CurrentPrincipal экземпляр нашего пользовательского принципала, в котором заполненный принципал будет иметь права полного доступа.

Вот поддельная CountryPickerViewModel, которой достаточно, чтобы вызвать ошибку:

public class CountryPickerViewModel
{
    public CountryPickerViewModel(IViewFactory viewFactory, 
                IViewModelFactory viewModelFactory, 
                ICoreBusinessLogicFactory businessLogicFactory, 
                ICacheFactory cacheFactory)
    {
        Items = new Collection<int>();
        var validator = ValidationFactory.CreateValidator<object>();
    }

    public int SelectedItem { get; set; }
    public Collection<int> Items { get; private set; }

}

Это взрыв ValidationFactory, который взрывается. ValidationFactory - это объект Enterprise Library, который пытается получить доступ к конфигурации.

1 ответ

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

Другие вопросы по тегам