Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/base http test server #10

Closed
wants to merge 17 commits into from
Closed
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
@@ -0,0 +1,20 @@
namespace ForEvolve.XUnit.HttpTests
{
public interface ITestServerStartupHttpTestServerBuilder : IHttpTestServerBuilder<TestServerStartup>
{
IHttpTestServer Create<TStatusCodeProvider>()
where TStatusCodeProvider : class, IStatusCodeProvider;

IHttpTestServer Create<TStatusCodeProvider, TResponseProvider>()
where TStatusCodeProvider : class, IStatusCodeProvider
where TResponseProvider : class, IResponseProvider;

IHttpTestServer Create(IStatusCodeProvider statusCodeProvider);
IHttpTestServer Create(IStatusCodeProvider statusCodeProvider, IResponseProvider responseProvider);

IHttpTestServer Create<TStatusCodeProvider>(IResponseProvider responseProvider)
where TStatusCodeProvider : class, IStatusCodeProvider;
IHttpTestServer Create<TResponseProvider>(IStatusCodeProvider statusCodeProvider)
where TResponseProvider : class, IResponseProvider;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace ForEvolve.XUnit.HttpTests
{
public class EmptyResponseForPathProvider : IResponseProvider
{
private readonly string _expectedPath;
private readonly string _expectedMethod;

public EmptyResponseForPathProvider(string expectedMethod, string expectedPath)
{
_expectedPath = expectedPath ?? throw new ArgumentNullException(nameof(expectedPath));
_expectedMethod = expectedMethod ?? throw new ArgumentNullException(nameof(expectedMethod));
}

public string ResponseText(HttpContext context)
{
var samePath = context.Request.Path.Value == _expectedPath;
var sameMethod = context.Request.Method == _expectedMethod;
if (samePath && sameMethod)
{
return "";
}
throw new WrongEndpointException(
_expectedMethod, _expectedPath,
context.Request.Method, context.Request.Path.Value
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ForEvolve.XUnit.HttpTests
{
public class EmptyResponseProvider : IResponseProvider
{
public string ResponseText(HttpContext context)
{
return "";
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;

Expand All @@ -7,28 +9,28 @@ namespace ForEvolve.XUnit.HttpTests
public class JsonPathResponseProvider : IResponseProvider
{
private readonly object _successObject;
private readonly object _failureObject;
private readonly string _expectedPath;
private readonly string _expectedMethod;

public JsonPathResponseProvider(string expectedMethod, string expectedPath, object successObject, object failureObject)
public JsonPathResponseProvider(string expectedMethod, string expectedPath, object successObject)
{
_expectedPath = expectedPath ?? throw new ArgumentNullException(nameof(expectedPath));
_expectedMethod = expectedMethod ?? throw new ArgumentNullException(nameof(expectedMethod));
_successObject = successObject ?? throw new ArgumentNullException(nameof(successObject));
_failureObject = failureObject ?? throw new ArgumentNullException(nameof(failureObject));
}

public string ResponseText(HttpContext context)
{
if (context.Request.Path.Value == _expectedPath)
var samePath = context.Request.Path.Value == _expectedPath;
var sameMethod = context.Request.Method == _expectedMethod;
if (samePath && sameMethod)
{
if (context.Request.Method == _expectedMethod)
{
return JsonConvert.SerializeObject(_successObject);
}
return JsonConvert.SerializeObject(_successObject);
}
return JsonConvert.SerializeObject(_failureObject);
throw new WrongEndpointException(
_expectedMethod, _expectedPath,
context.Request.Method, context.Request.Path.Value
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class BadRequestStatusCodeProvider : StatusCodeProvider
{
public BadRequestStatusCodeProvider() : base(StatusCodes.Status400BadRequest) { }
public const int ExpectedStatusCode = StatusCodes.Status400BadRequest;
public BadRequestStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class CreatedStatusCodeProvider : StatusCodeProvider
{
public CreatedStatusCodeProvider() : base(StatusCodes.Status201Created) { }
public const int ExpectedStatusCode = StatusCodes.Status201Created;

public CreatedStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class ForbiddenStatusCodeProvider : StatusCodeProvider
{
public ForbiddenStatusCodeProvider() : base(StatusCodes.Status403Forbidden) { }
public const int ExpectedStatusCode = StatusCodes.Status403Forbidden;

public ForbiddenStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class InternalServerErrorStatusCodeProvider : StatusCodeProvider
{
public InternalServerErrorStatusCodeProvider() : base(StatusCodes.Status500InternalServerError) { }
public const int ExpectedStatusCode = StatusCodes.Status500InternalServerError;

public InternalServerErrorStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Http;

namespace ForEvolve.XUnit.HttpTests
{
public sealed class NoContentStatusCodeProvider : StatusCodeProvider
{
public const int ExpectedStatusCode = StatusCodes.Status204NoContent;

public NoContentStatusCodeProvider() : base(ExpectedStatusCode) { }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class NotFoundStatusCodeProvider : StatusCodeProvider
{
public NotFoundStatusCodeProvider() : base(StatusCodes.Status404NotFound) { }
public const int ExpectedStatusCode = StatusCodes.Status404NotFound;

public NotFoundStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class OkStatusCodeProvider : StatusCodeProvider
{
public OkStatusCodeProvider() : base(StatusCodes.Status200OK) { }
public const int ExpectedStatusCode = StatusCodes.Status200OK;

public OkStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace ForEvolve.XUnit.HttpTests
{
public sealed class UnauthorizedStatusCodeProvider : StatusCodeProvider
{
public UnauthorizedStatusCodeProvider() : base(StatusCodes.Status401Unauthorized) { }
public const int ExpectedStatusCode = StatusCodes.Status401Unauthorized;

public UnauthorizedStatusCodeProvider() : base(ExpectedStatusCode) { }
}
}
3 changes: 1 addition & 2 deletions src/ForEvolve.XUnit/HttpTests/TestServerStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ public class TestServerStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IStatusCodeProvider, OkStatusCodeProvider>();
services.TryAddSingleton<IResponseProvider, EchoResponseProvider>();
services.TryAddSingleton<IResponseProvider, EmptyResponseProvider>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using Microsoft.Extensions.DependencyInjection;
using System;

namespace ForEvolve.XUnit.HttpTests
{
public class TestServerStartupHttpTestServerBuilder : HttpTestServerBuilder<TestServerStartup>, ITestServerStartupHttpTestServerBuilder
{
private readonly Action<IServiceCollection> _configureServices;
public const string ArrangeNotSupportedExceptionMessage = "You must register an IStatusCodeProvider for the TestServerStartup class to return an HTTP status code. Impossible to use this method, use another Arange method instead.";

public TestServerStartupHttpTestServerBuilder(Action<IServiceCollection> configureServices = null)
{
_configureServices = configureServices;
}

public override IHttpTestServer Create()
{
throw new NotSupportedException(ArrangeNotSupportedExceptionMessage);
}

public virtual IHttpTestServer Create<TStatusCodeProvider>()
where TStatusCodeProvider : class, IStatusCodeProvider
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IStatusCodeProvider, TStatusCodeProvider>();
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create<TStatusCodeProvider, TResponseProvider>()
where TStatusCodeProvider : class, IStatusCodeProvider
where TResponseProvider : class, IResponseProvider
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IStatusCodeProvider, TStatusCodeProvider>();
services.AddTransient<IResponseProvider, TResponseProvider>();
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create(IStatusCodeProvider statusCodeProvider)
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient(x => statusCodeProvider);
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create(IResponseProvider responseProvider)
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient(x => responseProvider);
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create(IStatusCodeProvider statusCodeProvider, IResponseProvider responseProvider)
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient(x => statusCodeProvider);
services.AddTransient(x => responseProvider);
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create<TStatusCodeProvider>(IResponseProvider responseProvider)
where TStatusCodeProvider : class, IStatusCodeProvider
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IStatusCodeProvider, TStatusCodeProvider>();
services.AddTransient(x => responseProvider);
_configureServices?.Invoke(services);
});
});
}

public virtual IHttpTestServer Create<TResponseProvider>(IStatusCodeProvider statusCodeProvider)
where TResponseProvider : class, IResponseProvider
{
return Create(hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient(x => statusCodeProvider);
services.AddTransient<IResponseProvider, TResponseProvider>();
_configureServices?.Invoke(services);
});
});
}
}
}
28 changes: 28 additions & 0 deletions src/ForEvolve.XUnit/HttpTests/WrongEndpointException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ForEvolve.XUnit.HttpTests
{
public class WrongEndpointException : ForEvolveException
{
public WrongEndpointException(
string expectedMethod, string expectedPath,
string actualMethod, string actualPath
)
:base($"Expected: {expectedMethod} {expectedPath} | Actual: {actualMethod} {actualPath}")
{
ExpectedMethod = expectedMethod;
ExpectedPath = expectedPath;
ActualMethod = actualMethod;
ActualPath = actualPath;
}

public string ExpectedMethod { get; }
public string ExpectedPath { get; }
public string ActualMethod { get; }
public string ActualPath { get; }
}
}
16 changes: 15 additions & 1 deletion test/ForEvolve.XUnit.Tests/HttpTests/BaseHttpTestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ namespace ForEvolve.XUnit.HttpTests
{
public class BaseHttpTestTest : BaseHttpTest<TestServerStartup>
{
private bool _configureWebHostBuilderHasBeenCalled = false;

protected override IWebHostBuilder ConfigureWebHostBuilder(IWebHostBuilder webHostBuilder)
{
_configureWebHostBuilderHasBeenCalled = true;
return base.ConfigureWebHostBuilder(webHostBuilder);
}

[Fact]
public void Should_call_ConfigureWebHostBuilder()
{
Assert.True(_configureWebHostBuilderHasBeenCalled);
}

[Fact]
public async Task Should_setup_the_client_and_the_server()
{
Expand All @@ -35,7 +49,7 @@ public class ConfigureServicesTest : BaseHttpTest<TestServerStartup>
protected override void ConfigureServices(IServiceCollection services)
{
// Arrange
services.TryAddSingleton<IStatusCodeProvider, CreatedStatusCodeProvider>();
services.AddSingleton<IStatusCodeProvider, CreatedStatusCodeProvider>();
}

[Fact]
Expand Down
Loading