Модульное тестирование pscmdlet в PowerShell с использованием C#
Нужна помощь в понимании модульного тестирования модуля PowerShell, который я создаю.
Я использую пакет PowerShellStandard.Library для создания некоторых командлетов. Мои команды являются производными от pscmdlet, а не от cmdlet, поскольку мне нужно манипулировать переменными SessionState.
Я создал новый проект модульного тестирования, и я искал некоторые учебные пособия (например, https://www.hanselman.com/blog/TestingPowerShellScriptsWithNUnit.aspx), где я обнаружил, что мне нужно использовать класс Runspace для выполнения pscmdlet. Проблема в том, что приведенная ниже команда всегда возвращает пустое пространство выполнения:
Runspace runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault2());
Кто-нибудь экспериментировал с этим в последнее время и есть идеи?
0 ответов
Я разместил аналогичный вопрос, и проблема в том, что я пытался использоватьPowerShellStandard.Library
Также пакет NuGet. Вместо этого вы хотите использовать пакет NuGet https://www.nuget.org/packages/Microsoft.PowerShell.SDK/.
У меня также есть пример настройки репозитория, в котором показано, как запускать тесты xUnit для командлета C# PowerShell Core.
Мне не удалось заставить его работать с Runspace, но я смог провести модульное тестирование своих PSCmdlets. К сожалению, решение, которое я нашел, не очень удовлетворило. Я добавил метод выставления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 от Microsoft. Я надеюсь, что однажды это изменится, но на данный момент это достаточно разумно.