如何用更改Thread.CurrentPrincipal的代码编写MSpec规范?

时间:2010-02-10 21:24:29

标签: .net multithreading security mspec

我一直在将一些旧规范转换为MSpec(使用NUnit / SpecUnit)。规范是针对视图模型的,并且所讨论的视图模型执行一些自定义安全检查。我们的规范中有一个帮助方法,它将为Thread.CurrentPrincipal设置虚假的安全凭证。这在旧的单元测试中运行良好,但在MSpec中失败了。具体来说,我得到了这个例外:

  

“System.Runtime.Serialization.SerializationException:未解析成员”

的类型

当部分SUT尝试读取应用配置文件时,会发生这种情况。如果我注释掉设置CurrentPrincipal的行(或者只是在检查配置文件的部分之后调用它),则错误消失,但由于缺少凭据而导致测试失败。

同样,如果我将CurrentPrincipal设置为null,则错误消失,但测试失败,因为未设置凭据。我已经google了这一点,并发现了一些关于确保自定义主体在跨越AppDomain边界(通常是参考Web应用程序)时可序列化的帖子。在我们的例子中,这不是一个Web应用程序,我没有跨越任何AppDomains。我们的pincipal对象也是可序列化的。

我下载了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的行为功能。此特定类模拟用户从绑定到此VM的(WPF)控件中选择某些内容。 SetupFakeSecurityCredentials()方法只是将Thread.CurrentPrincipal设置为我们的自定义主体的实例,其中已填充的prinipal将具有完全访问权限。

这是一个假的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是一个企业库对象,它试图访问配置。

1 个答案:

答案 0 :(得分:1)

请参阅this question了解测试运行失败的原因。