.net 如何使用MSpec为更改Thread.CurrentPrincipal的代码编写规范?
我一直在将一些旧规范转换为MSpec(使用NUnit/SpecUnit)。这些规范是针对视图模型的,并且所讨论的视图模型执行一些自定义安全检查。在我们的规范中有一个helper方法,它将为Thread.CurrentPrincipal设置假安全凭据。这在旧的单元测试中运行良好,但在MSpec中失败。具体来说,我得到了一个例外: “System.Runtime.Serialization.SerializationException:未解析成员的类型” 当SUT的一部分尝试读取应用程序配置文件时,就会发生这种情况。如果我注释掉设置CurrentPrincipal的行(或者在检查配置文件的部分之后调用它),错误就会消失,但是由于缺少凭据,测试失败 类似地,如果我将CurrentPrincipal设置为null,错误就会消失,但是测试再次失败,因为没有设置凭据。我在谷歌上搜索过这篇文章,发现了一些关于确保自定义主体在跨越AppDomain边界(通常指web应用)时可序列化的帖子。在我们的例子中,这不是一个web应用程序,我也没有跨越任何应用程序域。我们的pincipal对象也是可序列化的 我下载了MSpec的源代码,发现ConsoleRunner调用了一个名为AppDomainRunner的类。我还没有调试到它,但它看起来像是运行在不同的应用程序域的规格 那么,有人对我如何克服这个问题有什么想法吗?我真的很喜欢MSpec,并且很想专门使用它。但我需要能够在运行测试时提供假安全凭据 以下是规范类:.net 如何使用MSpec为更改Thread.CurrentPrincipal的代码编写规范?,.net,multithreading,security,mspec,.net,Multithreading,Security,Mspec,我一直在将一些旧规范转换为MSpec(使用NUnit/SpecUnit)。这些规范是针对视图模型的,并且所讨论的视图模型执行一些自定义安全检查。在我们的规范中有一个helper方法,它将为Thread.CurrentPrincipal设置假安全凭据。这在旧的单元测试中运行良好,但在MSpec中失败。具体来说,我得到了一个例外: “System.Runtime.Serialization.SerializationException:未解析成员的类型” 当SUT的一部分尝试读取应用程序配置文件时,
[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;
}
[主题(类型(CountryPickerViewModel))]
用户进行选择时的公共类:PickerViewModelSpecsBase
{
受保护的静态CountryPickerViewModel选择器;
建立上下文=()=>
{
SetupFakeSecurityCredentials();
CreateFactoryStubs();
StubLookupServicer()
.WithData(BuildActiveItems(新[]{“美国”、“英国”}));
picker=新的CountryPickerViewModel(ViewFactory、ViewModelFactory、,
BusinessLogicFactory、CacheFactory);
};
因为=()=>
picker.SelectedItem=picker.Items[0];
表现得像一个有选择的选择器;
}
我们有许多这样的“选取器”视图模型,它们都表现出一些常见的行为。所以我使用的是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; }
}
公共类CountryPickerViewModel
{
公共CountryPickerViewModel(IViewFactory viewFactory,
IViewModelFactory viewModelFactory,
ICoreBusinessLogicFactory业务逻辑工厂,
ICACHE工厂(工厂)
{
Items=新集合();
var validator=ValidationFactory.CreateValidator();
}
public int SelectedItem{get;set;}
公共集合项{get;private set;}
}
这是ValidationFactory的呼叫,它爆炸了。ValidationFactory是一个企业库对象,它尝试访问配置。有关测试运行失败的原因,请参阅。有关测试运行失败的原因,请参阅。Dan,请发布示例代码,以便我们更容易调试您描述的行为?是的,测试在单独的AppDomain中运行,这样DLL的.config就可以由您的规范获取。再一次,在测试中设置Thread.CurrentPrincipal并从app.config读取值对我来说就像一股气味。这是应该驻留在单独类中的行为,这些类很容易在视图模型规范中存根。我同意你关于气味的两点。我们担心注入实际执行安全检查的代码,因为调用者可以很容易地做同样的事情(使用他们自己的实现),从而绕过我们的安全检查。另一方面,从理论上讲,他们也可以像我们在测试中一样在线程上伪造凭证。不确定什么是最好的方法。至于配置访问,这实际上是由企业库完成的。那完全是另一个话题Dan,你可以发布示例代码,让我们更容易调试你描述的行为吗?是的,测试在单独的AppDomain中运行,这样DLL的.config就可以由您的规范获取。再一次,在测试中设置Thread.CurrentPrincipal并从app.config读取值对我来说就像一股气味。这是应该驻留在单独类中的行为,这些类很容易在视图模型规范中存根。我同意你关于气味的两点。我们担心注入实际执行安全检查的代码,因为调用者可以很容易地做同样的事情(使用他们自己的实现),从而绕过我们的安全检查。另一方面,从理论上讲,他们也可以像我们在测试中一样在线程上伪造凭证。不确定什么是最好的方法。至于配置访问,这实际上是由企业库完成的。那完全是另一个话题