140 lines
4.4 KiB
C#
140 lines
4.4 KiB
C#
namespace PS.IPAM.Tests.Mocks;
|
|
|
|
using System.Management.Automation;
|
|
using System.Management.Automation.Host;
|
|
using System.Reflection;
|
|
|
|
/// <summary>
|
|
/// Helper class for testing PowerShell cmdlets.
|
|
/// </summary>
|
|
public class CmdletTestHelper<T> : IDisposable where T : PSCmdlet, new()
|
|
{
|
|
private readonly T _cmdlet;
|
|
private readonly List<object> _output = new();
|
|
private readonly List<ErrorRecord> _errors = new();
|
|
private bool _disposed;
|
|
|
|
public CmdletTestHelper()
|
|
{
|
|
_cmdlet = new T();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the cmdlet instance for setting parameters.
|
|
/// </summary>
|
|
public T Cmdlet => _cmdlet;
|
|
|
|
/// <summary>
|
|
/// Gets the output objects written by the cmdlet.
|
|
/// </summary>
|
|
public IReadOnlyList<object> Output => _output.AsReadOnly();
|
|
|
|
/// <summary>
|
|
/// Gets the errors written by the cmdlet.
|
|
/// </summary>
|
|
public IReadOnlyList<ErrorRecord> Errors => _errors.AsReadOnly();
|
|
|
|
/// <summary>
|
|
/// Gets whether any errors were written.
|
|
/// </summary>
|
|
public bool HasErrors => _errors.Count > 0;
|
|
|
|
/// <summary>
|
|
/// Invokes the cmdlet and captures output.
|
|
/// </summary>
|
|
public void Invoke()
|
|
{
|
|
// Use reflection to call the protected ProcessRecord method
|
|
var processMethod = typeof(T).GetMethod("ProcessRecord",
|
|
BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
if (processMethod == null)
|
|
{
|
|
throw new InvalidOperationException("ProcessRecord method not found on cmdlet.");
|
|
}
|
|
|
|
// Set up a mock command runtime to capture output
|
|
var runtime = new MockCommandRuntime(_output, _errors);
|
|
var runtimeProperty = typeof(Cmdlet).GetProperty("CommandRuntime",
|
|
BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
runtimeProperty?.SetValue(_cmdlet, runtime);
|
|
|
|
// Invoke the method
|
|
try
|
|
{
|
|
processMethod.Invoke(_cmdlet, null);
|
|
}
|
|
catch (TargetInvocationException ex) when (ex.InnerException != null)
|
|
{
|
|
// Unwrap the exception
|
|
throw ex.InnerException;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
_disposed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mock implementation of ICommandRuntime for capturing cmdlet output.
|
|
/// This is a minimal implementation that only handles the methods we need for testing.
|
|
/// </summary>
|
|
internal class MockCommandRuntime : ICommandRuntime
|
|
{
|
|
private readonly List<object> _output;
|
|
private readonly List<ErrorRecord> _errors;
|
|
|
|
public MockCommandRuntime(List<object> output, List<ErrorRecord> errors)
|
|
{
|
|
_output = output;
|
|
_errors = errors;
|
|
}
|
|
|
|
public PSHost Host => null!;
|
|
public PSTransactionContext CurrentPSTransaction => null!;
|
|
|
|
public bool ShouldContinue(string query, string caption) => true;
|
|
public bool ShouldContinue(string query, string caption, ref bool yesToAll, ref bool noToAll) => true;
|
|
public bool ShouldProcess(string target) => true;
|
|
public bool ShouldProcess(string target, string action) => true;
|
|
public bool ShouldProcess(string verboseDescription, string verboseWarning, string caption) => true;
|
|
public bool ShouldProcess(string verboseDescription, string verboseWarning, string caption, out ShouldProcessReason shouldProcessReason)
|
|
{
|
|
shouldProcessReason = ShouldProcessReason.None;
|
|
return true;
|
|
}
|
|
|
|
public bool TransactionAvailable() => false;
|
|
|
|
public void ThrowTerminatingError(ErrorRecord errorRecord) => throw errorRecord.Exception;
|
|
|
|
public void WriteCommandDetail(string text) { }
|
|
public void WriteDebug(string text) { }
|
|
public void WriteError(ErrorRecord errorRecord) => _errors.Add(errorRecord);
|
|
public void WriteObject(object sendToPipeline) => _output.Add(sendToPipeline);
|
|
public void WriteObject(object sendToPipeline, bool enumerateCollection)
|
|
{
|
|
if (enumerateCollection && sendToPipeline is System.Collections.IEnumerable enumerable)
|
|
{
|
|
foreach (var item in enumerable)
|
|
{
|
|
_output.Add(item);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_output.Add(sendToPipeline);
|
|
}
|
|
}
|
|
public void WriteProgress(ProgressRecord progressRecord) { }
|
|
public void WriteProgress(long sourceId, ProgressRecord progressRecord) { }
|
|
public void WriteVerbose(string text) { }
|
|
public void WriteWarning(string text) { }
|
|
}
|