forked from oskardudycz/EventSourcing.NetCore
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Untangled Core.WebApi and Core.Api.Testing from main Core domain proj…
…ect to enable also samples using other patterns
- Loading branch information
1 parent
e833db9
commit c70f599
Showing
36 changed files
with
310 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.TestHost; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Xunit; | ||
|
||
namespace Core.Api.Testing | ||
{ | ||
public abstract class ApiFixture<TStartup>: ApiFixture where TStartup : class | ||
{ | ||
public override TestContext CreateTestContext() => | ||
new TestContext<TStartup>(GetConfiguration, SetupServices, SetupWebHostBuilder); | ||
} | ||
|
||
public abstract class ApiFixture: IAsyncLifetime | ||
{ | ||
protected readonly TestContext Sut; | ||
|
||
protected HttpClient Client => Sut.Client; | ||
|
||
protected TestServer Server => Sut.Server; | ||
|
||
protected abstract string ApiUrl { get; } | ||
|
||
protected virtual Dictionary<string, string> GetConfiguration(string fixtureName) => new(); | ||
|
||
protected virtual Action<IServiceCollection>? SetupServices => null; | ||
|
||
protected virtual Func<IWebHostBuilder, IWebHostBuilder>? SetupWebHostBuilder => null; | ||
|
||
protected ApiFixture() | ||
{ | ||
Environment.SetEnvironmentVariable("SchemaName", GetType().Name.ToLower()); | ||
|
||
Sut = CreateTestContext(); | ||
} | ||
|
||
public virtual TestContext CreateTestContext() => new(GetConfiguration, SetupServices, SetupWebHostBuilder); | ||
|
||
public virtual Task InitializeAsync() => Task.CompletedTask; | ||
|
||
public virtual Task DisposeAsync() => Task.CompletedTask; | ||
|
||
public async Task<HttpResponseMessage> Get(string path = "", int maxNumberOfRetries = 0, int retryIntervalInMs = 1000, Func<HttpResponseMessage, ValueTask<bool>>? check = null) | ||
{ | ||
HttpResponseMessage queryResponse; | ||
var retryCount = maxNumberOfRetries; | ||
|
||
var doCheck = check ?? (response => new (response.StatusCode == HttpStatusCode.OK)); | ||
do | ||
{ | ||
queryResponse = await Client.GetAsync( | ||
$"{ApiUrl}/{path}" | ||
); | ||
|
||
if (retryCount == 0 || (await doCheck(queryResponse))) | ||
break; | ||
|
||
await Task.Delay(retryIntervalInMs); | ||
retryCount--; | ||
} while (true); | ||
return queryResponse; | ||
} | ||
|
||
public Task<HttpResponseMessage> Post(string path, object request) | ||
{ | ||
return Client.PostAsync( | ||
$"{ApiUrl}/{path}", | ||
request.ToJsonStringContent() | ||
); | ||
} | ||
|
||
public Task<HttpResponseMessage> Post(object request) | ||
{ | ||
return Post(string.Empty, request); | ||
} | ||
|
||
public Task<HttpResponseMessage> Put(string path, object? request = null) | ||
{ | ||
return Client.PutAsync( | ||
$"{ApiUrl}/{path}", | ||
request != null ? | ||
request.ToJsonStringContent() | ||
: new StringContent(string.Empty) | ||
); | ||
} | ||
|
||
public Task<HttpResponseMessage> Put(object request) | ||
{ | ||
return Put(string.Empty, request); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net5.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<IsTestProject>false</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" /> | ||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" /> | ||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" /> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="FluentAssertions" Version="5.10.3" /> | ||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.8" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Core.Api.Testing | ||
{ | ||
public static class TestWebHostBuilder | ||
{ | ||
public static IWebHostBuilder Create(Dictionary<string, string> configuration, Action<IServiceCollection>? configureServices = null) | ||
{ | ||
var projectDir = Directory.GetCurrentDirectory(); | ||
configureServices ??= _ => { }; | ||
|
||
return new WebHostBuilder() | ||
.UseEnvironment("Development") | ||
.UseContentRoot(projectDir) | ||
.UseConfiguration(new ConfigurationBuilder() | ||
.SetBasePath(projectDir) | ||
.AddJsonFile("appsettings.json", true) | ||
.AddInMemoryCollection(configuration) | ||
.Build() | ||
) | ||
.ConfigureServices(configureServices); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,61 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Core.Api.Testing; | ||
using Core.Commands; | ||
using Core.Events; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Core.Events.External; | ||
using Core.Requests; | ||
using MediatR; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Xunit; | ||
using Shipments.Api.Tests.Core; | ||
|
||
namespace Core.Testing | ||
{ | ||
public abstract class ApiFixture<TStartup>: ApiFixture where TStartup : class | ||
public abstract class ApiWithEventsFixture<TStartup>: Api.Testing.ApiFixture<TStartup> where TStartup : class | ||
{ | ||
public override TestContext CreateTestContext() => | ||
new TestContext<TStartup>(GetConfiguration, SetupServices, SetupWebHostBuilder); | ||
} | ||
|
||
public abstract class ApiFixture: IAsyncLifetime | ||
{ | ||
protected readonly TestContext Sut; | ||
|
||
private HttpClient Client => Sut.Client; | ||
private readonly EventsLog eventsLog = new(); | ||
private readonly DummyExternalEventProducer externalEventProducer = new(); | ||
private readonly DummyExternalCommandBus externalCommandBus = new(); | ||
|
||
protected abstract string ApiUrl { get; } | ||
public override TestContext CreateTestContext() => | ||
new TestContext<TStartup>(GetConfiguration, (services) => | ||
{ | ||
SetupServices?.Invoke(services); | ||
services.AddSingleton(eventsLog); | ||
services.AddSingleton(typeof(INotificationHandler<>), typeof(EventListener<>)); | ||
services.AddSingleton<IExternalEventProducer>(externalEventProducer); | ||
services.AddSingleton<IExternalCommandBus>(externalCommandBus); | ||
services.AddSingleton<IExternalEventConsumer, DummyExternalEventConsumer>(); | ||
protected virtual Dictionary<string, string> GetConfiguration(string fixtureName) => new(); | ||
}, SetupWebHostBuilder); | ||
|
||
protected virtual Action<IServiceCollection>? SetupServices => null; | ||
|
||
protected virtual Func<IWebHostBuilder, IWebHostBuilder>? SetupWebHostBuilder => null; | ||
|
||
protected ApiFixture() | ||
public IReadOnlyCollection<TEvent> PublishedExternalEventsOfType<TEvent>() where TEvent : IExternalEvent | ||
{ | ||
Environment.SetEnvironmentVariable("SchemaName", GetType().Name.ToLower()); | ||
|
||
Sut = CreateTestContext(); | ||
return externalEventProducer.PublishedEvents.OfType<TEvent>().ToList(); | ||
} | ||
|
||
public virtual TestContext CreateTestContext() => new(GetConfiguration, SetupServices, SetupWebHostBuilder); | ||
|
||
public virtual Task InitializeAsync() => Task.CompletedTask; | ||
|
||
public virtual Task DisposeAsync() => Task.CompletedTask; | ||
|
||
public async Task<HttpResponseMessage> Get(string path = "", int maxNumberOfRetries = 0, int retryIntervalInMs = 1000, Func<HttpResponseMessage, ValueTask<bool>>? check = null) | ||
public IReadOnlyCollection<TCommand> PublishedExternalCommandOfType<TCommand>() where TCommand : ICommand | ||
{ | ||
HttpResponseMessage queryResponse; | ||
var retryCount = maxNumberOfRetries; | ||
|
||
var doCheck = check ?? (response => new (response.StatusCode == HttpStatusCode.OK)); | ||
do | ||
{ | ||
queryResponse = await Client.GetAsync( | ||
$"{ApiUrl}/{path}" | ||
); | ||
|
||
if (retryCount == 0 || (await doCheck(queryResponse))) | ||
break; | ||
|
||
await Task.Delay(retryIntervalInMs); | ||
retryCount--; | ||
} while (true); | ||
return queryResponse; | ||
return externalCommandBus.SentCommands.OfType<TCommand>().ToList(); | ||
} | ||
|
||
public Task<HttpResponseMessage> Post(string path, object request) | ||
public async Task PublishInternalEvent(IEvent @event) | ||
{ | ||
return Client.PostAsync( | ||
$"{ApiUrl}/{path}", | ||
request.ToJsonStringContent() | ||
); | ||
using var scope = Server.Host.Services.CreateScope(); | ||
var eventBus = scope.ServiceProvider.GetRequiredService<IEventBus>(); | ||
await eventBus.Publish(@event); | ||
} | ||
|
||
public Task<HttpResponseMessage> Post(object request) | ||
public IReadOnlyCollection<TEvent> PublishedInternalEventsOfType<TEvent>() | ||
{ | ||
return Post(string.Empty, request); | ||
return eventsLog.PublishedEvents.OfType<TEvent>().ToList(); | ||
} | ||
} | ||
|
||
public IReadOnlyCollection<TEvent> PublishedExternalEventsOfType<TEvent>() where TEvent : IExternalEvent | ||
=> Sut.PublishedExternalEventsOfType<TEvent>(); | ||
|
||
public IReadOnlyCollection<TEvent> PublishedInternalEventsOfType<TEvent>() where TEvent : IEvent | ||
=> Sut.PublishedInternalEventsOfType<TEvent>(); | ||
public abstract class ApiWithEventsFixture: Api.Testing.ApiFixture | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.