いくつかの古い仕様を MSpec に変換しています (NUnit/SpecUnit を使用していました)。仕様はビュー モデル用であり、問題のビュー モデルはいくつかのカスタム セキュリティ チェックを行います。仕様には、Thread.CurrentPrincipal の偽のセキュリティ資格情報をセットアップするヘルパー メソッドがあります。これは、古い単体テストでは問題なく機能しましたが、MSpec では失敗します。具体的には、次の例外が発生します。
「System.Runtime.Serialization.SerializationException: メンバーの型が解決されていません」
これは、SUT の一部がアプリの構成ファイルを読み取ろうとしたときに発生します。CurrentPrincipal を設定する行をコメント アウトすると (または構成ファイルをチェックする部分の後に単に呼び出すと)、エラーはなくなりますが、資格情報がないためにテストが失敗します。
同様に、CurrentPrincipal を null に設定すると、エラーはなくなりますが、資格情報が設定されていないため、テストは再び失敗します。これをグーグルで調べたところ、カスタム プリンシパルが AppDomain の境界を越えたときにシリアル化可能であることを確認することに関する投稿がいくつか見つかりました (通常は Web アプリに関して)。私たちの場合、これは Web アプリではなく、AppDomains を超えていません。私たちの重要なオブジェクトもシリアライズ可能です。
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 の Behaviors 機能を使用しています。この特定のクラスは、この 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 は、構成にアクセスしようとする Enterprise Library オブジェクトです。