我一直在将一些旧规范转换为 MSpec(使用 NUnit/SpecUnit)。规范是针对视图模型的,并且有问题的视图模型会进行一些自定义安全检查。我们的规范中有一个辅助方法,它将为 Thread.CurrentPrincipal 设置虚假的安全凭证。这在旧的单元测试中运行良好,但在 MSpec 中失败。具体来说,我得到了这个例外:
“System.Runtime.Serialization.SerializationException:没有为成员解析类型”
当 SUT 的一部分尝试读取应用程序配置文件时会发生这种情况。如果我注释掉设置 CurrentPrincipal 的行(或者只是在检查配置文件的部分之后调用它),错误就会消失,但由于缺少凭据,测试会失败。
同样,如果我将 CurrentPrincipal 设置为 null,错误就会消失,但测试再次失败,因为未设置凭据。我用谷歌搜索了这个,发现了一些关于确保自定义主体在跨越 AppDomain 边界时可序列化的帖子(通常参考网络应用程序)。在我们的例子中,这不是一个网络应用程序,我没有跨越任何 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 设置为我们自定义主体的实例,其中已填充主体将完全访问权限。
这是一个足以导致错误的假 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 是一个企业库对象,它尝试访问配置。