カスタムプロバイダを単体テストするには?

PowerShellでカスタムプロバイダを作っていて、ある程度複雑になってくると単体テストをしたくなってくる。

でも、カスタムプロバイダで実装するメソッドはそのほとんどがprotectedなため、自前でカスタムプロバイダをインスタンス化してテストする事はできない。それにPowerShellからはプロバイダの色々なメソッドが複雑に呼び出されるため、それを完全にエミュレートすることは現実的ではない。

じゃあカスタムプロバイダから処理を切り離してクラスを作って、それをテストすればいいんじゃね?なんていう話になる。たしかに切り離す事ができるような処理はそれでいいけど、単体テストしたいのはPowerShell上で正常に動作するかどうかということなので、それじゃ意味がない。

何か方法はないかと考えていて、試しにやってみたら案外簡単にできた。

例えば「HogeProvider」というカスタムプロバイダを単体テストする場合

[Test]
public void テスト() {
    RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
    rsConfig.Providers.Append(
        new ProviderConfigurationEntry("Hoge", typeof(HogeProvider), "")
    );
    using(RunspaceInvoke rsEngine = new RunspaceInvoke(rsConfig)) {
        // このプロバイダは「Hoge:」というドライブを自動的に割り当てる
        rsEngine.Invoke("cd Hoge:");
        Collection<PSObject> result = rsEngine.Invoke("dir");

        Assert.That(result, Has.Property("Count", 3));
    }
}

RunspaceConfigurationというクラスをインスタンス化し、ProvidersプロパティにHogeProviderの設定を追加する。こうすることでSnapInをインストールしなくても直接プロバイダを登録できる*1

あとはこの設定からRunspaceInvokeクラスをインスタンス化して、テストしたいコマンドをInvokeメソッドで実行していくだけ。

これを使えばカスタムプロバイダのほとんどの機能を単体テストできるんじゃないだろうか。

*1:既にHogeProviderがSnapInとしてインストールされている場合はバッティングするので注意