Async command unit tests

This commit is contained in:
Frank Ray 2023-05-19 17:19:17 +01:00 committed by GitHub
parent 1ee2653cf8
commit 0ec70a44db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 158 additions and 5 deletions

View File

@ -135,6 +135,52 @@ public sealed class CommandAppTester
var result = app.Run(args);
var output = console.Output
.NormalizeLineEndings()
.TrimLines()
.Trim();
return new CommandAppResult(result, output, context, settings);
}
/// <summary>
/// Runs the command application asynchronously.
/// </summary>
/// <param name="args">The arguments.</param>
/// <returns>The result.</returns>
public async Task<CommandAppResult> RunAsync(params string[] args)
{
var console = new TestConsole().Width(int.MaxValue);
return await RunAsync(args, console);
}
private async Task<CommandAppResult> RunAsync(string[] args, TestConsole console, Action<IConfigurator>? config = null)
{
CommandContext? context = null;
CommandSettings? settings = null;
var app = new CommandApp(Registrar);
_appConfiguration?.Invoke(app);
if (_configuration != null)
{
app.Configure(_configuration);
}
if (config != null)
{
app.Configure(config);
}
app.Configure(c => c.ConfigureConsole(console));
app.Configure(c => c.SetInterceptor(new CallbackCommandInterceptor((ctx, s) =>
{
context = ctx;
settings = s;
})));
var result = await app.RunAsync(args);
var output = console.Output
.NormalizeLineEndings()
.TrimLines()

View File

@ -0,0 +1,28 @@
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommand : AsyncCommand<AsynchronousCommandSettings>
{
private readonly IAnsiConsole _console;
public AsynchronousCommand(IAnsiConsole console)
{
_console = console;
}
public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings)
{
// Simulate a long running asynchronous task
await Task.Delay(200);
if (settings.ThrowException)
{
throw new Exception($"Throwing exception asynchronously");
}
else
{
_console.WriteLine($"Finished executing asynchronously");
}
return 0;
}
}

View File

@ -6,8 +6,4 @@ public sealed class ThrowingCommand : Command<ThrowingCommandSettings>
{
throw new InvalidOperationException("W00t?");
}
}
public sealed class ThrowingCommandSettings : CommandSettings
{
}
}

View File

@ -0,0 +1,8 @@
namespace Spectre.Console.Tests.Data;
public sealed class AsynchronousCommandSettings : CommandSettings
{
[CommandOption("--ThrowException")]
[DefaultValue(false)]
public bool ThrowException { get; set; }
}

View File

@ -0,0 +1,5 @@
namespace Spectre.Console.Tests.Data;
public sealed class ThrowingCommandSettings : CommandSettings
{
}

View File

@ -0,0 +1,70 @@
namespace Spectre.Console.Tests.Unit.Cli;
public sealed partial class CommandAppTests
{
public sealed class Async
{
[Fact]
public async void Should_Execute_Command_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await app.RunAsync();
// Then
result.ExitCode.ShouldBe(0);
result.Output.ShouldBe("Finished executing asynchronously");
}
[Fact]
public async void Should_Handle_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
// When
var result = await app.RunAsync(new[]
{
"--ThrowException",
"true",
});
// Then
result.ExitCode.ShouldBe(-1);
}
[Fact]
public async void Should_Throw_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});
// When
var result = await Record.ExceptionAsync(async () =>
await app.RunAsync(new[]
{
"--ThrowException",
"true",
}));
// Then
result.ShouldBeOfType<Exception>().And(ex =>
{
ex.Message.ShouldBe("Throwing exception asynchronously");
});
}
}
}