Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Alba;
using FluentValidation;
using IntegrationTests;
using JasperFx.CodeGeneration;
using Marten;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
Expand All @@ -12,153 +13,156 @@ namespace Wolverine.Http.Tests.Bugs;

public class Bug_2182_unresolved_IProblemDetailSource
{
private readonly WebApplicationBuilder _builder;
private readonly WebApplicationBuilder _builder;

public Bug_2182_unresolved_IProblemDetailSource()
{
_builder = WebApplication.CreateBuilder([]);

_builder.Services.AddMarten(Servers.PostgresConnectionString);
_builder.Services.DisableAllWolverineMessagePersistence();
_builder.Services.DisableAllExternalWolverineTransports();

_builder.Services.AddWolverineHttp();
}

[Fact]
public async Task can_not_compile_with_manual_discovery_by_default()
{
_builder.Services.AddWolverine(ExtensionDiscovery.ManualOnly, opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation(); // from Wolverine.FluentValidation
// ExtensionDiscovery.ManualMode and Wolverine.Http.FluentValidation services are not registered
});

await using var host = await AlbaHost.For(_builder, app =>
public Bug_2182_unresolved_IProblemDetailSource()
{
app.MapWolverineEndpoints(opts =>
{
opts.UseFluentValidationProblemDetailMiddleware();
});
});
_builder = WebApplication.CreateBuilder([]);

var result = await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(500);
});

result.ReadAsText()
.ShouldContain(
"JasperFx was unable to resolve a variable of type " +
"Wolverine.Http.FluentValidation.IProblemDetailSource<Wolverine.Http.Tests.Bugs.Bug_2182_Endpoint.Request> " +
"as part of the method POST_Bug_2182.Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)");
}

[Fact]
public async Task can_compile_with_manual_extension_discovery_when_problem_detail_services_are_registered()
{
_builder.Services.AddWolverine(ExtensionDiscovery.ManualOnly, opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation(); // from Wolverine.FluentValidation
opts.UseFluentValidationProblemDetail(); // from Wolverine.Http.FluentValidation
});
_builder.Services.AddMarten(Servers.PostgresConnectionString);
_builder.Services.DisableAllWolverineMessagePersistence();
_builder.Services.DisableAllExternalWolverineTransports();

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
{
opts.UseFluentValidationProblemDetailMiddleware();
});
});
_builder.Services.AddWolverineHttp();
}

await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(200);
});
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task can_compile_with_default_extension_discovery(bool useFluentValidationProblemDetail)
{
_builder.Services.AddWolverine(opts =>
[Fact]
public async Task can_not_compile_with_manual_discovery_by_default()
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation();
if (useFluentValidationProblemDetail)
opts.UseFluentValidationProblemDetail();
});
_builder.Services.AddWolverine(ExtensionDiscovery.ManualOnly, opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation(); // from Wolverine.FluentValidation
// ExtensionDiscovery.ManualMode and Wolverine.Http.FluentValidation services are not registered
});

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
opts.UseFluentValidationProblemDetailMiddleware());
});

// UnResolvableVariableException can be returned in 2 ways:
// either as a failed scenario result or thrown explicitly.
// The actual way is not important here, but the error itself is.
var errorMessage = string.Empty;
try
{
var result = await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(500);
});
errorMessage = await result.ReadAsTextAsync();
}
catch (UnResolvableVariableException ex)
{
errorMessage = ex.Message;
}

errorMessage.ShouldContain(
"JasperFx was unable to resolve a variable of type " +
"Wolverine.Http.FluentValidation.IProblemDetailSource<Wolverine.Http.Tests.Bugs.Bug_2182_Endpoint.Request> " +
"as part of the method POST_Bug_2182.Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)");
}

await using var host = await AlbaHost.For(_builder, app =>
[Fact]
public async Task can_compile_with_manual_extension_discovery_when_problem_detail_services_are_registered()
{
app.MapWolverineEndpoints(opts =>
{
opts.UseFluentValidationProblemDetailMiddleware();
});
});
_builder.Services.AddWolverine(ExtensionDiscovery.ManualOnly, opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation(); // from Wolverine.FluentValidation
opts.UseFluentValidationProblemDetail(); // from Wolverine.Http.FluentValidation
});

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
opts.UseFluentValidationProblemDetailMiddleware());
});

await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(200);
});
}

await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(200);
});
}

[Theory]
[InlineData(ExtensionDiscovery.ManualOnly, true)]
[InlineData(ExtensionDiscovery.Automatic, true)]
[InlineData(ExtensionDiscovery.Automatic, false)]
public async Task can_validate_request_with_problem_detail_middleware(
ExtensionDiscovery extensionDiscovery, bool useFluentValidationProblemDetail)
{
_builder.Services.AddWolverine(extensionDiscovery, opts =>
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task can_compile_with_default_extension_discovery(bool useFluentValidationProblemDetail)
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation();
if (useFluentValidationProblemDetail)
opts.UseFluentValidationProblemDetail();
});
_builder.Services.AddWolverine(opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation();
if (useFluentValidationProblemDetail)
opts.UseFluentValidationProblemDetail();
});

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
opts.UseFluentValidationProblemDetailMiddleware());
});

await host.Scenario(x =>
{
x.Post.Json(new Bug_2182_Endpoint.Request("valid")).ToUrl("/Bug_2182");
x.StatusCodeShouldBe(200);
});
}

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
{
opts.UseFluentValidationProblemDetailMiddleware();
});
});

var invalidRequest = new Bug_2182_Endpoint.Request(string.Empty);
var results = await host.Scenario(x =>
[Theory]
[InlineData(ExtensionDiscovery.ManualOnly, true)]
[InlineData(ExtensionDiscovery.Automatic, true)]
[InlineData(ExtensionDiscovery.Automatic, false)]
public async Task can_validate_request_with_problem_detail_middleware(
ExtensionDiscovery extensionDiscovery, bool useFluentValidationProblemDetail)
{
x.Post.Json(invalidRequest).ToUrl("/Bug_2182");
x.ContentTypeShouldBe("application/problem+json");
x.StatusCodeShouldBe(400);
});
}
_builder.Services.AddWolverine(extensionDiscovery, opts =>
{
opts.Discovery.IncludeAssembly(typeof(Bug_2182_Endpoint.Request).Assembly);
opts.UseFluentValidation();
if (useFluentValidationProblemDetail)
opts.UseFluentValidationProblemDetail();
});

await using var host = await AlbaHost.For(_builder, app =>
{
app.MapWolverineEndpoints(opts =>
opts.UseFluentValidationProblemDetailMiddleware());
});

var invalidRequest = new Bug_2182_Endpoint.Request(string.Empty);
var results = await host.Scenario(x =>
{
x.Post.Json(invalidRequest).ToUrl("/Bug_2182");
x.ContentTypeShouldBe("application/problem+json");
x.StatusCodeShouldBe(400);
});
}
}

public static class Bug_2182_Endpoint
{
[WolverinePost("/Bug_2182")]
public static IResult Post(Request value)
{
return TypedResults.Ok(value);
}

public record Request(string Title)
{
public class Validator : AbstractValidator<Request>
[WolverinePost("/Bug_2182")]
public static IResult Post(Request value)
{
return TypedResults.Ok(value);
}

public record Request(string Title)
{
public Validator()
{
RuleFor(x => x.Title)
.NotEmpty();
}
public class Validator : AbstractValidator<Request>
{
public Validator()
{
RuleFor(x => x.Title)
.NotEmpty();
}
}
}
}
}
82 changes: 82 additions & 0 deletions src/Http/Wolverine.Http.Tests/Bugs/Bug_using_host_stop.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Alba;
using Microsoft.AspNetCore.Builder;
using Shouldly;
using System.Reflection;
using Wolverine.Runtime;
using Wolverine.Tracking;

namespace Wolverine.Http.Tests.Bugs;

public class Bug_using_host_stop
{
[Fact]
public async Task stops_wolverine_runtime_when_created_via_host_builder()
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For(builder, _ => { });
var runtime = host.GetRuntime();
var checkPoints = new bool[3];

checkPoints[0] = IsRunning(runtime);
await host.StopAsync();
checkPoints[1] = IsRunning(runtime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(runtime);

// Note WolverineRuntime is stopped when host.StopAsync() is called,
// which is expected as WolverineRuntime is IHostedService.
checkPoints.ShouldBe([true, false, false]);
}

[Fact]
public async Task does_not_stop_wolverine_runtime_when_created_via_web_factory()
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For<WolverineWebApi.Program>(_ => { });
var wolverineRuntime = host.GetRuntime();
var checkPoints = new bool[3];

checkPoints[0] = IsRunning(wolverineRuntime);
await host.StopAsync();
checkPoints[1] = IsRunning(wolverineRuntime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(wolverineRuntime);

// If you expect host.StopAsync() to stop WolverineRuntime -
// [true, false, false] - it's not the case here.
checkPoints.ShouldBe([true, true, false]);
}

[Fact]
public async Task wolverine_runtime_can_be_stopped_explicitly_when_created_via_web_factory()
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For<WolverineWebApi.Program>(_ => { });
var wolverineRuntime = host.GetRuntime();
var checkPoints = new bool[3];

checkPoints[0] = IsRunning(wolverineRuntime);
await host.GetRuntime().StopAsync(default); // Can be stopped explicitly.
await host.StopAsync();
checkPoints[1] = IsRunning(wolverineRuntime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(wolverineRuntime);

checkPoints.ShouldBe([true, false, false]);
}

static bool IsRunning(WolverineRuntime runtime)
{
var field = typeof(WolverineRuntime).GetField("_hasStopped", BindingFlags.NonPublic | BindingFlags.Instance);
return (bool?)field?.GetValue(runtime) == false;
}
}
Loading
Loading