namespace PS.IPAM.Tests.Mocks;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Reflection;
///
/// Helper class for testing PowerShell cmdlets.
///
public class CmdletTestHelper : IDisposable where T : PSCmdlet, new()
{
private readonly T _cmdlet;
private readonly List _output = new();
private readonly List _errors = new();
private bool _disposed;
public CmdletTestHelper()
{
_cmdlet = new T();
}
///
/// Gets the cmdlet instance for setting parameters.
///
public T Cmdlet => _cmdlet;
///
/// Gets the output objects written by the cmdlet.
///
public IReadOnlyList Output => _output.AsReadOnly();
///
/// Gets the errors written by the cmdlet.
///
public IReadOnlyList Errors => _errors.AsReadOnly();
///
/// Gets whether any errors were written.
///
public bool HasErrors => _errors.Count > 0;
///
/// Invokes the cmdlet and captures output.
///
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;
}
}
}
///
/// Mock implementation of ICommandRuntime for capturing cmdlet output.
/// This is a minimal implementation that only handles the methods we need for testing.
///
internal class MockCommandRuntime : ICommandRuntime
{
private readonly List _output;
private readonly List _errors;
public MockCommandRuntime(List output, List 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) { }
}