diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Protacon.NetCore.WebApi.TestUtil.Tests.csproj b/Protacon.NetCore.WebApi.TestUtil.Tests/Protacon.NetCore.WebApi.TestUtil.Tests.csproj index e74fa25..851d1df 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Protacon.NetCore.WebApi.TestUtil.Tests.csproj +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Protacon.NetCore.WebApi.TestUtil.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/TestStartup.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/TestStartup.cs index 8ac8fd9..30a12cc 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/TestStartup.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/TestStartup.cs @@ -6,8 +6,6 @@ using Protacon.NetCore.WebApi.TestUtil.Tests.Dummy; using Xunit; -[assembly: CollectionBehavior(DisableTestParallelization = true)] - namespace Protacon.NetCore.WebApi.TestUtil.Tests { public class TestStartup @@ -22,7 +20,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(Substitute.For()); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { loggerFactory.AddDebug(); app.UseMvc(); diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/BasicFlowTests.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/BasicFlowTests.cs index a3b2cf0..5b65901 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/BasicFlowTests.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/BasicFlowTests.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Threading.Tasks; using FluentAssertions; using Protacon.NetCore.WebApi.TestUtil.Tests.Dummy; using Xunit; @@ -8,60 +9,65 @@ namespace Protacon.NetCore.WebApi.TestUtil.Tests.Tests public class BasicFlowTests { [Fact] - public void WhenGetIsCalled_ThenAssertingItWorks() + public async Task WhenGetIsCalled_ThenAssertingItWorks() { - TestHost.Run().Get("/returnthree/") + var foo = await TestHost.Run().Get("/returnthree/") + .ExpectStatusCode(HttpStatusCode.OK) + .WithContentOf(); + + await TestHost.Run().Get("/returnthree/") .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing( x => x.Should().Be(3)); TestHost.Run().Get("/returnthree/") - .Invoking(x => x.ExpectStatusCode(HttpStatusCode.NoContent)) - .Should().Throw(); + .Awaiting(x => x.ExpectStatusCode(HttpStatusCode.NoContent)) + .Should() + .Throw(); } [Fact] - public void WhenDeleteIsCalled_ThenAssertingItWorks() + public async Task WhenDeleteIsCalled_ThenAssertingItWorks() { - TestHost.Run().Delete("/something/abc") + await TestHost.Run().Delete("/something/abc") .ExpectStatusCode(HttpStatusCode.NoContent); TestHost.Run().Delete("/something/abc") - .Invoking(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) + .Awaiting(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) .Should().Throw(); } [Fact] - public void WhenPutIsCalled_ThenAssertingItWorks() + public async Task WhenPutIsCalled_ThenAssertingItWorks() { - TestHost.Run().Put("/returnsame/", new DummyRequest { Value = "3" }) + await TestHost.Run().Put("/returnsame/", new DummyRequest { Value = "3" }) .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Value.Should().Be("3")); TestHost.Run().Put("/returnsame/", new { value = 3 }) - .Invoking(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) + .Awaiting(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) .Should().Throw(); } [Fact] - public void WhenPostIsCalled_ThenAssertingItWorks() + public async Task WhenPostIsCalled_ThenAssertingItWorks() { - TestHost.Run().Post("/returnsame/", new DummyRequest { Value = "3" }) + await TestHost.Run().Post("/returnsame/", new DummyRequest { Value = "3" }) .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Value.Should().Be("3")); TestHost.Run().Post("/returnsame/", new { value = 3 }) - .Invoking(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) + .Awaiting(x => x.ExpectStatusCode(HttpStatusCode.NotFound)) .Should().Throw(); } [Fact] - public void WhenNonAcceptedCodeIsExpected_ThenAcceptItAsResult() + public async Task WhenNonAcceptedCodeIsExpected_ThenAcceptItAsResult() { - TestHost.Run().Get("/errorcontent/") + await TestHost.Run().Get("/errorcontent/") .ExpectStatusCode(HttpStatusCode.NotFound) .WithContentOf() .Passing(x => x.Value.Should().Be("error")); @@ -71,7 +77,7 @@ public void WhenNonAcceptedCodeIsExpected_ThenAcceptItAsResult() public void WhenExpectedCodeIsNotDefinedOnError_ThenFail() { TestHost.Run().Get("/errorcontent/") - .Invoking(x => x.WithContentOf()) + .Awaiting(x => x.WithContentOf()) .Should().Throw(); } } diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/HeaderSupportTest.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/HeaderSupportTest.cs index 768c9aa..430ba9f 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/HeaderSupportTest.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/HeaderSupportTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Threading.Tasks; using FluentAssertions; using Xunit; @@ -9,13 +10,14 @@ namespace Protacon.NetCore.WebApi.TestUtil.Tests.Tests public class HeaderSupportTest { [Fact] - public void WhenHeadersAreDefined_ThenPassThemToApi() + public async Task WhenHeadersAreDefined_ThenPassThemToApi() { - TestHost.Run().Get("/headertest/", + await TestHost.Run().Get("/headertest/", headers: new Dictionary {{"example", "somevalue"}}) .ExpectStatusCode(HttpStatusCode.NoContent); - TestHost.Run().Invoking(x => x.Get("/headertest/", + TestHost.Run() + .Awaiting(x => x.Get("/headertest/", headers: new Dictionary {{"somethingElse", "somevalue"}}) .ExpectStatusCode(HttpStatusCode.NoContent)) .Should().Throw(); diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/MockDepenciesTests.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/MockDepenciesTests.cs index f1cbd61..5d12f03 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/MockDepenciesTests.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/MockDepenciesTests.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Threading.Tasks; using FluentAssertions; using NSubstitute; using Protacon.NetCore.WebApi.TestUtil.Tests.Dummy; @@ -9,14 +10,14 @@ namespace Protacon.NetCore.WebApi.TestUtil.Tests.Tests public class MockDepenciesTests { [Fact] - public void WhenHeadersAreDefined_ThenPassThemToApi() + public async Task WhenHeadersAreDefined_ThenPassThemToApi() { var host = TestHost.Run(); // See TestStartup for information what is done before this. host.Setup(x => x.SomeCall(Arg.Is("abc")).Returns("3")); - host.Get("/external/abc") + await host.Get("/external/abc") .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Value.Should().Be("3")); diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/NonCommonDatatypeTests.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/NonCommonDatatypeTests.cs index 38a7e87..347d124 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/NonCommonDatatypeTests.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/NonCommonDatatypeTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Text; +using System.Threading.Tasks; using FluentAssertions; using Xunit; @@ -10,18 +11,18 @@ namespace Protacon.NetCore.WebApi.TestUtil.Tests.Tests public class NonCommonDatatypeTests { [Fact] - public void WhenFileIsDownloaded_ThenResultsCanBeAsserted() + public async Task WhenFileIsDownloaded_ThenResultsCanBeAsserted() { - TestHost.Run().Get("/file/") + await TestHost.Run().Get("/file/") .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Length.Should().Be(4)); } [Fact] - public void WhenHtmlPageIsReturned_ThenResultsCanBeAsserted() + public async Task WhenHtmlPageIsReturned_ThenResultsCanBeAsserted() { - TestHost.Run().Get("/page/") + await TestHost.Run().Get("/page/") .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Should().Contain("Hello World")); diff --git a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/WaitForStatusCodeTests.cs b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/WaitForStatusCodeTests.cs index 515543e..7c79442 100644 --- a/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/WaitForStatusCodeTests.cs +++ b/Protacon.NetCore.WebApi.TestUtil.Tests/Tests/WaitForStatusCodeTests.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Threading.Tasks; using FluentAssertions; using Protacon.NetCore.WebApi.TestUtil.Extensions; using Xunit; @@ -12,7 +13,7 @@ public class WaitForStatusCodeTests public void WhenErronousCodeIsReturned_ThenThrowErrorAfterTimeout() { TestHost.Run().Get("/returnthree/") - .Invoking(x => x.WaitForStatusCode(HttpStatusCode.BadRequest, TimeSpan.FromSeconds(2))) + .Awaiting(x => x.WaitForStatusCode(HttpStatusCode.BadRequest, TimeSpan.FromSeconds(2))) .Should().Throw(); } @@ -20,7 +21,7 @@ public void WhenErronousCodeIsReturned_ThenThrowErrorAfterTimeout() public void WhenValidCodeIsReturned_ThenReturnWithoutError() { TestHost.Run().Get("/returnthree/") - .Invoking(x => x.WaitForStatusCode(HttpStatusCode.OK, TimeSpan.FromSeconds(2))) + .Awaiting(x => x.WaitForStatusCode(HttpStatusCode.OK, TimeSpan.FromSeconds(2))) .Should().NotThrow(); } } diff --git a/Protacon.NetCore.WebApi.TestUtil/CallData.cs b/Protacon.NetCore.WebApi.TestUtil/CallData.cs index 6255b59..4557bd6 100644 --- a/Protacon.NetCore.WebApi.TestUtil/CallData.cs +++ b/Protacon.NetCore.WebApi.TestUtil/CallData.cs @@ -1,30 +1,12 @@ -using System; - -namespace Protacon.NetCore.WebApi.TestUtil +namespace Protacon.NetCore.WebApi.TestUtil { public class CallData { - private readonly T _data; + internal readonly T Data; public CallData(T data) { - _data = data; - } - - public CallData Passing(Action asserts) - { - asserts.Invoke(_data); - return this; - } - - public TSelect Select(Func selector) - { - return selector.Invoke(_data); - } - - public T Select() - { - return _data; + Data = data; } } } diff --git a/Protacon.NetCore.WebApi.TestUtil/CallDataExtensions.cs b/Protacon.NetCore.WebApi.TestUtil/CallDataExtensions.cs new file mode 100644 index 0000000..3c5570d --- /dev/null +++ b/Protacon.NetCore.WebApi.TestUtil/CallDataExtensions.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; + +namespace Protacon.NetCore.WebApi.TestUtil +{ + public static class CallDataExtensions + { + public static async Task> Passing(this Task> dataWrapperTask, Action asserts) + { + var wrappedData = await dataWrapperTask; + asserts(wrappedData.Data); + return wrappedData; + } + + public static async Task Select(this Task> dataWrapperTask, Func selector) + { + var wrappedData = await dataWrapperTask; + return selector.Invoke(wrappedData.Data); + } + + public static async Task Select(this Task> dataWrapperTask) + { + var data = await dataWrapperTask; + return data.Data; + } + } +} diff --git a/Protacon.NetCore.WebApi.TestUtil/CallExtensions.cs b/Protacon.NetCore.WebApi.TestUtil/CallExtensions.cs new file mode 100644 index 0000000..e4358e8 --- /dev/null +++ b/Protacon.NetCore.WebApi.TestUtil/CallExtensions.cs @@ -0,0 +1,100 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Protacon.NetCore.WebApi.TestUtil +{ + public static class CallExtensions + { + public static async Task ExpectStatusCode(this Task callTask, HttpStatusCode code) + { + var call = await callTask.ConfigureAwait(false); + var httpCall = await call.HttpTask.ConfigureAwait(false); + + if (httpCall.StatusCode != code) + { + throw new ExpectedStatusCodeException($"Expected statuscode '{code}' but got '{(int)httpCall.StatusCode}'"); + } + + call.ExpectedStatusCode = code; + + return call; + } + + public static async Task HeaderPassing(this Task callTask, string header, Action assertsForValue) + { + var call = await callTask.ConfigureAwait(false); + var response = await call.HttpTask.ConfigureAwait(false); + + var match = response.Headers + .SingleOrDefault(x => x.Key == header); + + if (match.Equals(default(KeyValuePair>))) + throw new InvalidOperationException($"Header '{header}' not found, available headers are '{HeadersAsReadableList(response)}'"); + + assertsForValue.Invoke(match.Value.Single()); + + return call; + } + + private static string HeadersAsReadableList(HttpResponseMessage message) + { + return message.Headers.Select(x => x.Key.ToString()).Aggregate("", (a, b) => $"{a}, {b}"); + } + + public static async Task> WithContentOf(this Task callTask) + { + var call = await callTask.ConfigureAwait(false); + var result = await call.HttpTask.ConfigureAwait(false); + var code = (int)result.StatusCode; + + var content = await result.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + + if ((code > 299 || code < 199) && code != (int?)call.ExpectedStatusCode) + throw new ExpectedStatusCodeException( + $"Tried to get data from non ok statuscode response, expected status is '2xx' or '{call.ExpectedStatusCode}' but got '{code}' with content '{Encoding.Default.GetString(content)}'"); + + if (!result.Content.Headers.Contains("Content-Type")) + throw new InvalidOperationException("Response didn't contain any 'Content-Type'. Reason may be that you didn't return anything?"); + + var contentType = result.Content.Headers.Single(x => x.Key == "Content-Type").Value.FirstOrDefault() ?? ""; + + + switch (contentType) + { + case var ctype when ctype.StartsWith("application/json"): + return ParseJson(content); + case "application/pdf": + if (typeof(T) != typeof(byte[])) + throw new InvalidOperationException("Only output type of 'byte[]' is supported for 'application/pdf'."); + + return new CallData((T)(object)content.ToArray()); + default: + if (typeof(T) != typeof(string)) + throw new InvalidOperationException($"Only output type of 'string' is supported for '{contentType}'."); + + return new CallData((T)(object)Encoding.Default.GetString(content)); + } + } + + private static CallData ParseJson(byte[] content) + { + var asString = Encoding.Default.GetString(content); + + try + { + var asObject = JsonConvert.DeserializeObject(asString); + return new CallData(asObject); + } + catch (JsonSerializationException) + { + throw new InvalidOperationException($"Cannot serialize '{asString}' as type '{typeof(T)}'"); + } + } + } +} diff --git a/Protacon.NetCore.WebApi.TestUtil/CallResponse.cs b/Protacon.NetCore.WebApi.TestUtil/CallResponse.cs index 84d8e6b..fe9888b 100644 --- a/Protacon.NetCore.WebApi.TestUtil/CallResponse.cs +++ b/Protacon.NetCore.WebApi.TestUtil/CallResponse.cs @@ -1,102 +1,31 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; +using System; using System.Net; using System.Net.Http; +using System.Threading.Tasks; namespace Protacon.NetCore.WebApi.TestUtil { + // HttpResponse is wrapped because we don't want add extension methods + // to HttpResponseMessage directly because + // - they pollute intellisense and user may use those extensions as crazy ways. + // - extend chain with possible metadata like ExpectedStatusCode call does. + // - Support cases where same call must be executed multiple times like polling certain status code. public class Call { - private HttpStatusCode? _expectedCode; - private Func _httpCall; - private readonly Lazy _response; + internal HttpStatusCode? ExpectedStatusCode { get; set; } - public Call(Func httpCall) - { - _response = new Lazy(httpCall); - _httpCall = httpCall; - } - - public Call ExpectStatusCode(HttpStatusCode code) - { - if (_response.Value.StatusCode != code) - { - throw new ExpectedStatusCodeException($"Expected statuscode '{code}' but got '{(int)_response.Value.StatusCode}'"); - } - - _expectedCode = code; - - return this; - } - - public Call HeaderPassing(string header, Action assertsForValue) - { - var match = _response.Value.Headers - .SingleOrDefault(x => x.Key == header); - - if (match.Equals(default(KeyValuePair>))) - throw new InvalidOperationException($"Header '{header}' not found, available headers are '{HeadersAsReadableList()}'"); - - assertsForValue.Invoke(match.Value.Single()); - - return this; - } - - private string HeadersAsReadableList() - { - return _response.Value.Headers.Select(x => x.Key.ToString()).Aggregate("", (a, b) => $"{a}, {b}"); - } - - public CallData WithContentOf() - { - var code = (int)_response.Value.StatusCode; - - if ((code > 299 || code < 199) && code != (int?)_expectedCode) - throw new ExpectedStatusCodeException( - $"Tried to get data from non ok statuscode response, expected status is '2xx' or '{_expectedCode}' but got '{code}' with content '{_response.Value.Content.ReadAsStringAsync().Result}'"); - - if (!_response.Value.Content.Headers.Contains("Content-Type")) - throw new InvalidOperationException("Response didn't contain any 'Content-Type'. Reason may be that you didn't return anything?"); - - var contentType = _response.Value.Content.Headers.Single(x => x.Key == "Content-Type").Value.FirstOrDefault() ?? ""; - - switch (contentType) - { - case var ctype when ctype.StartsWith("application/json"): - return ParseJson(); - case "application/pdf": - if(typeof(T) != typeof(byte[])) - throw new InvalidOperationException("Only output type of 'byte[]' is supported for 'application/pdf'."); - - var data = (object)_response.Value.Content.ReadAsByteArrayAsync().Result.ToArray(); - return new CallData((T)data); - default: - if (typeof(T) != typeof(string)) - throw new InvalidOperationException($"Only output type of 'string' is supported for '{contentType}'."); - - var result = (object)_response.Value.Content.ReadAsStringAsync().Result; - return new CallData((T)result); - } - } + internal Task HttpTask { get; } + private readonly Func> _httpTaskFactory; - internal Call Clone() + public Call(Func> httpCall) { - return new Call(_httpCall); + _httpTaskFactory = httpCall; + HttpTask = httpCall.Invoke(); } - private CallData ParseJson() + internal Task Clone() { - try - { - var asObject = JsonConvert.DeserializeObject(_response.Value.Content.ReadAsStringAsync().Result); - return new CallData(asObject); - } - catch (JsonSerializationException) - { - throw new InvalidOperationException($"Cannot serialize '{_response.Value.Content.ReadAsStringAsync().Result}' as type '{typeof(T)}'"); - } + return Task.Run(() => new Call(_httpTaskFactory)); } } } diff --git a/Protacon.NetCore.WebApi.TestUtil/Extensions/CallResponseExtensions.cs b/Protacon.NetCore.WebApi.TestUtil/Extensions/CallResponseExtensions.cs index be89a64..f6b0199 100644 --- a/Protacon.NetCore.WebApi.TestUtil/Extensions/CallResponseExtensions.cs +++ b/Protacon.NetCore.WebApi.TestUtil/Extensions/CallResponseExtensions.cs @@ -7,7 +7,7 @@ namespace Protacon.NetCore.WebApi.TestUtil.Extensions { public static class CallResponseExtensions { - public static Call WaitForStatusCode(this Call call, HttpStatusCode statusCode, TimeSpan timeout) + public static async Task WaitForStatusCode(this Task call, HttpStatusCode statusCode, TimeSpan timeout) { const int testPeriodMs = 500; var timeUsedMs = 0; @@ -16,7 +16,7 @@ public static Call WaitForStatusCode(this Call call, HttpStatusCode statusCode, { try { - return call.Clone().ExpectStatusCode(statusCode); + return await (await call).Clone().ExpectStatusCode(statusCode).ConfigureAwait(false); } catch (ExpectedStatusCodeException ex) { diff --git a/Protacon.NetCore.WebApi.TestUtil/TestHost.cs b/Protacon.NetCore.WebApi.TestUtil/TestHost.cs index f435828..1f13fe2 100644 --- a/Protacon.NetCore.WebApi.TestUtil/TestHost.cs +++ b/Protacon.NetCore.WebApi.TestUtil/TestHost.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net.Http; using System.Text; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; @@ -12,61 +13,49 @@ namespace Protacon.NetCore.WebApi.TestUtil { public static class TestHost { - public static Call Get(this TestServer server, string uri, Dictionary headers = null) + public static Task Get(this TestServer server, string uri, Dictionary headers = null) { - return new Call(() => + return Task.Run(() => new Call(() => { - using (var client = server.CreateClient()) - { - AddHeadersIfAny(headers, client); - return client.GetAsync(uri).Result; - } - }); + var client = server.CreateClient(); + AddHeadersIfAny(headers, client); + return client.GetAsync(uri); + })); } - public static Call Post(this TestServer server, string path, object data, Dictionary headers = null) + public static Task Post(this TestServer server, string path, object data, Dictionary headers = null) { - return new Call(() => + return Task.Run(() => new Call(() => { - using (var client = server.CreateClient()) - { - AddHeadersIfAny(headers, client); - - var content = JsonConvert.SerializeObject(data); - return client.PostAsync(path, new StringContent(content, Encoding.UTF8, "application/json")).Result; - } - }); + var client = server.CreateClient(); + AddHeadersIfAny(headers, client); + + var content = JsonConvert.SerializeObject(data); + return client.PostAsync(path, new StringContent(content, Encoding.UTF8, "application/json")); + })); } - public static Call Put(this TestServer server, string path, object data, Dictionary headers = null) + public static Task Put(this TestServer server, string path, object data, Dictionary headers = null) { - return new Call(() => + return Task.Run(() => new Call(() => { - using (var client = server.CreateClient()) - { - AddHeadersIfAny(headers, client); - - var content = JsonConvert.SerializeObject(data); - return client - .PutAsync(path, new StringContent(content, Encoding.UTF8, "application/json")) - .Result; - } - }); + var client = server.CreateClient(); + AddHeadersIfAny(headers, client); + + var content = JsonConvert.SerializeObject(data); + return client.PutAsync(path, new StringContent(content, Encoding.UTF8, "application/json")); + })); } - public static Call Delete(this TestServer server, string path, Dictionary headers = null) + public static Task Delete(this TestServer server, string path, Dictionary headers = null) { - return new Call(() => + return Task.Run(() => new Call(() => { - using (var client = server.CreateClient()) - { - AddHeadersIfAny(headers, client); - - return client - .DeleteAsync(path) - .Result; - } - }); + var client = server.CreateClient(); + AddHeadersIfAny(headers, client); + + return client.DeleteAsync(path); + })); } private static void AddHeadersIfAny(Dictionary headers, HttpClient client) diff --git a/Readme.md b/Readme.md index 1262f39..dd31e9b 100644 --- a/Readme.md +++ b/Readme.md @@ -8,9 +8,9 @@ This is lightweight wrapper and collection of useful tools to work with .Net Cor ## Example GET ```cs [Fact] - public void WhenGetIsCalled_ThenAssertingItWorks() + public async Task WhenGetIsCalled_ThenAssertingItWorks() { - TestHost.Run().Get("/returnthree/") + await TestHost.Run().Get("/returnthree/") .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing( @@ -21,9 +21,9 @@ This is lightweight wrapper and collection of useful tools to work with .Net Cor ## Example POST ```cs [Fact] - public void WhenPostIsCalled_ThenAssertingItWorks() + public async Task WhenPostIsCalled_ThenAssertingItWorks() { - TestHost.Run().Post("/returnsame/", new DummyRequest { Value = "3" }) + await TestHost.Run().Post("/returnsame/", new DummyRequest { Value = "3" }) .ExpectStatusCode(HttpStatusCode.OK) .WithContentOf() .Passing(x => x.Value.Should().Be("3")); @@ -61,11 +61,8 @@ This is lightweight wrapper and collection of useful tools to work with .Net Cor services.Configure(a => a.BaseUrl = "http://localhost:5000"); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app) { - loggerFactory.AddConsole(); - loggerFactory.AddDebug(); - app.UseMiddleware(); app.UseHangfireServer(); app.UseMvc();