1

需要一些帮助来了解如何对我正在创建的 PowerShell 模块进行单元测试。

我正在使用 PowerShellStandard.Library 包来创建一些 cmdlet。我的命令源自 pscmdlet 而不是 cmdlet,因为我确实需要操作 SessionState 变量。

我创建了一个新的单元测试项目,并搜索了一些教程(例如https://www.hanselman.com/blog/TestingPowerShellScriptsWithNUnit.aspx),我发现我确实需要使用 Runspace 类才能执行pscmdlet。问题是下面的命令总是返回一个空运行空间:

Runspace runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2());

有人最近在尝试这些并且有任何想法吗?

4

2 回答 2

2

我发布了一个类似的问题,最终问题是我也尝试使用PowerShellStandard.LibraryNuGet 包。相反,您希望使用Microsoft.PowerShell.SDK NuGet 包。

我还有一个示例 repo设置,它展示了如何针对 C# PowerShell Core cmdlet 运行 xUnit 测试。

于 2019-09-19T02:39:30.057 回答
0

我无法让它与运行空间一起工作,但我能够对我的 PSCmdlet 进行单元测试。不幸的是,我找到的解决方案并不是很令人满意。我添加了一个公开的方法,ProcessRecord如下所示:

[Cmdlet(VerbsCommon.Get, "AnExample")]
public class ExampleCmdlet : PSCmdlet
{
    public void ProcessInternal()
    {
        ProcessRecord();
    }
}

从单元测试调用 PSCmdlet 时,我会使用此方法:

var cmdlet = new ExampleCmdlet();
var proxy = new CommandRuntimeProxy();
cmdlet.CommandRuntime = proxy;
cmdlet.ProcessInternal();
var results = proxy.WrittenObjects.Select(obj => (T) obj).ToList();

CommandRuntimeProxy是一个接收对象的新类。这是重要的部分,但还有更多方法可以实现。

internal class CommandRuntimeProxy : ICommandRuntime
{
    public List<object> WrittenObjects { get; } = new List<object>();

    public bool ShouldContinue(string query, string caption)
    {
        return true;
    }

    public bool ShouldProcess(string target)
    {
        return true;
    }

    public void ThrowTerminatingError(ErrorRecord errorRecord)
    {
        throw new InvalidOperationException("Error in pipeline", errorRecord.Exception);
    }

    public void WriteError(ErrorRecord errorRecord)
    {
        throw new InvalidOperationException("Error in pipeline", errorRecord.Exception);
    }

    public void WriteObject(object sendToPipeline, bool enumerateCollection)
    {
        WriteObject(sendToPipeline);
    }

    public void WriteObject(object sendToPipeline)
    {
        WrittenObjects.Add(sendToPipeline);
    }
}

实际上,您可以使用此方法绕过大部分 Powershell 管道。到目前为止,它似乎工作得相当好,只要您使用对接口后面的 Powershell 运行时的隐藏访问来为您的测试带来好处。

我相信之所以会出现这种情况,是因为 Powershell 有点老,而且可能不像微软最近推出的 MVC 产品那样受到人们的喜爱。我希望这有一天会改变,但现在这已经足够合理了。

于 2019-09-10T16:19:56.113 回答