我无法让它与运行空间一起工作,但我能够对我的 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 产品那样受到人们的喜爱。我希望这有一天会改变,但现在这已经足够合理了。