Skip to content

Commit

Permalink
Merge branch 'main' into feature/add-patch-method-support
Browse files Browse the repository at this point in the history
  • Loading branch information
ardalis committed Sep 19, 2023
2 parents 59dab54 + 3069f73 commit 812d861
Show file tree
Hide file tree
Showing 16 changed files with 202 additions and 8 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public async Task ReturnsNotFoundGivenInvalidAuthorId()

All of these methods are extensions on `HttpClient`; the following samples assume `client` is an `HttpClient`. All methods take an optional `ITestOutputHelper`, which is an xUnit type.

#### [GET](src\Ardalis.HttpClientTestExtensions\HttpClientGetExtensionMethods.cs)
#### [GET](src/Ardalis.HttpClientTestExtensions/HttpClientGetExtensionMethods.cs)

```csharp
// GET and return an object T
Expand Down Expand Up @@ -115,7 +115,7 @@ await client.GetAndEnsureForbiddenAsync("/authors/1");
await client.GetAndEnsureNotFoundAsync("/authors/-1");
```

#### [POST](src\Ardalis.HttpClientTestExtensions\HttpClientPostExtensionMethods.cs)
#### [POST](src/Ardalis.HttpClientTestExtensions/HttpClientPostExtensionMethods.cs)

```csharp
// NOTE: There's a helper for this now, too (see below)
Expand Down Expand Up @@ -144,7 +144,7 @@ await client.PostAndEnsureForbiddenAsync("/authors", content);
await client.PostAndEnsureNotFoundAsync("/wrongendpoint", content)
```

#### [PUT](src\Ardalis.HttpClientTestExtensions\HttpClientPutExtensionMethods.cs)
#### [PUT](src/Ardalis.HttpClientTestExtensions/HttpClientPutExtensionMethods.cs)

```csharp
var content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json");
Expand Down Expand Up @@ -229,7 +229,7 @@ await client.DeleteAndEnsureForbiddenAsync("/authors/1");
await client.DeleteAndEnsureNotFoundAsync("/wrongendpoint");
```

### [HttpResponseMessage](src\Ardalis.HttpClientTestExtensions\HttpResponseMessageExtensionMethods.cs)
### [HttpResponseMessage](src/Ardalis.HttpClientTestExtensions/HttpResponseMessageExtensionMethods.cs)

All of these methods are extensions on `HttpResponseMessage`.

Expand Down Expand Up @@ -259,7 +259,7 @@ response.Ensure(HttpStatusCode.Created);
response.EnsureContainsAsync("OMG!", _testOutputHelper);
```

### [StringContentHelpers](src\Ardalis.HttpClientTestExtensions\StringContentHelpers.cs)
### [StringContentHelpers](src/Ardalis.HttpClientTestExtensions/StringContentHelpers.cs)

Extensions on `HttpContent` which you'll typically want to return a `StringContent` type as you serialize your DTO to JSON.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
<Summary>Functional/integration tests using WebApplicationFactory and HttpClient often have a lot of repetition. These extensions minimize the repetition so fetching and deserializing data from endpoints is one line of code per test.</Summary>
<RepositoryUrl>https://github.com/ardalis/HttpClientTestExtensions</RepositoryUrl>
<PackageTags>aspnet asp.net aspnetcore asp.net core api web api rest endpoint controller test integration functional xunit unit</PackageTags>
<PackageReleaseNotes>Fix StringContent FromModelAsJson Helper</PackageReleaseNotes>
<PackageReleaseNotes>Add NotAllowed extensions.</PackageReleaseNotes>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>4.0.0</Version>
<Version>4.1.0</Version>
<AssemblyName>Ardalis.HttpClientTestExtensions</AssemblyName>
<PackageIcon>icon.png</PackageIcon>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ public static async Task<HttpResponseMessage> DeleteAndEnsureNotFoundAsync(
return response;
}

/// <summary>
/// Ensures a DELETE to a requestUri returns a 405 Method Not Allowed response status code
/// </summary>
/// <param name="client"></param>
/// <param name="requestUri"></param>
/// <param name="output">Optional; used to provide details to standard output.</param>
/// <returns></returns>
public static async Task<HttpResponseMessage> DeleteAndEnsureMethodNotAllowedAsync(
this HttpClient client,
string requestUri,
ITestOutputHelper output = null)
{
var response = await client.DeleteAsync(requestUri, output);
response.EnsureMethodNotAllowed();
return response;
}

/// <summary>
/// Ensures a DELETE to a requestUri returns a 204 No Content response status code
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,23 @@ public static async Task<HttpResponseMessage> GetAndEnsureNotFoundAsync(
return response;
}

/// <summary>
/// Ensures a GET to a requestUri returns a 405 Method Not Allowed response status code
/// </summary>
/// <param name="client"></param>
/// <param name="requestUri"></param>
/// <param name="output">Optional; used to provide details to standard output.</param>
/// <returns></returns>
public static async Task<HttpResponseMessage> GetAndEnsureMethodNotAllowedAsync(
this HttpClient client,
string requestUri,
ITestOutputHelper output = null)
{
var response = await client.GetAsync(requestUri, output);
response.EnsureMethodNotAllowed();
return response;
}

/// <summary>
/// Makes a GET request to a requestUri and returns the response string
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ public static async Task<HttpResponseMessage> PostAndEnsureForbiddenAsync(
return response;
}

/// <summary>
/// Ensures a POST to a requestUri returns a 405 Method Not Allowed response status code
/// </summary>
/// <param name="client"></param>
/// <param name="requestUri"></param>
/// <param name="content"></param>
/// <param name="output">Optional; used to provide details to standard output.</param>
/// <returns></returns>
public static async Task<HttpResponseMessage> PostAndEnsureMethodNotAllowedAsync(
this HttpClient client,
string requestUri,
HttpContent content,
ITestOutputHelper output = null)
{
var response = await client.PostAsync(requestUri, content, output);
response.EnsureMethodNotAllowed();
return response;
}

/// <summary>
/// Makes a POST request to a requestUri and ensures the response contains a substring
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public static async Task<T> PutAndDeserializeAsync<T>(
return result;
}


/// <summary>
/// Ensures a PUT to a requestUri returns a 404 Not Found response status code
/// </summary>
Expand All @@ -50,6 +49,24 @@ public static async Task<HttpResponseMessage> PutAndEnsureNotFoundAsync(this Htt
return response;
}

/// <summary>
/// Ensures a PUT to a requestUri returns a 405 Method Not Allowed response status code
/// </summary>
/// <param name="client"></param>
/// <param name="requestUri"></param>
/// <param name="content"></param>
/// <param name="output">Optional; used to provide details to standard output.</param>
/// <returns></returns>
public static async Task<HttpResponseMessage> PutAndEnsureMethodNotAllowedAsync(this HttpClient client,
string requestUri,
HttpContent content,
ITestOutputHelper output = null)
{
var response = await client.PutAsync(requestUri, content, output);
response.EnsureMethodNotAllowed();
return response;
}

/// <summary>
/// Ensures a PUT to a requestUri returns a 401 Unauthorized response status code
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ public static void EnsureNotFound(this HttpResponseMessage response)
response.Ensure(HttpStatusCode.NotFound);
}

/// <summary>
/// Ensures a response has a status code 405 Method Not Allowed
/// </summary>
/// <param name="response"></param>
/// <return></return>
public static void EnsureMethodNotAllowed(this HttpResponseMessage response)
{
response.Ensure(HttpStatusCode.MethodNotAllowed);
}

/// <summary>
/// Ensures a response has a status code 204 No Content
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/Ardalis.HttpClientTestExtensions/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ await client.GetAndEnsureForbiddenAsync("/authors/1");

// GET and assert a 404 is returned
await client.GetAndEnsureNotFoundAsync("/authors/-1");

// GET and assert a 405 is returned
await client.GetAndEnsureMethodNotAllowedAsync("/wrongendpoint", content)
```

#### [POST](src\Ardalis.HttpClientTestExtensions\HttpClientPostExtensionMethods.cs)
Expand Down Expand Up @@ -138,6 +141,9 @@ await client.PostAndEnsureForbiddenAsync("/authors", content);

// POST and assert a 404 is returned
await client.PostAndEnsureNotFoundAsync("/wrongendpoint", content)

// POST and assert a 405 is returned
await client.PostAndEnsureMethodNotAllowedAsync("/wrongendpoint", content)
```

#### [PUT](src\Ardalis.HttpClientTestExtensions\HttpClientPutExtensionMethods.cs)
Expand Down Expand Up @@ -166,6 +172,9 @@ await client.PutAndEnsureForbiddenAsync("/authors/1", content);

// PUT and assert a 404 is returned
await client.PutAndEnsureNotFoundAsync("/wrongendpoint", content)

// PUT and assert a 405 is returned
await client.PutAndEnsureMethodNotAllowedAsync("/wrongendpoint", content)
```

#### [DELETE](src\Ardalis.HttpClientTestExtensions\HttpClientDeleteExtensionMethods.cs)
Expand Down Expand Up @@ -195,6 +204,9 @@ await client.DeleteAndEnsureForbiddenAsync("/authors/1");

// DELETE and assert a 404 is returned
await client.DeleteAndEnsureNotFoundAsync("/wrongendpoint");

// DELETE and assert a 405 is returned
await client.DeleteAndEnsureMethodNotAllowedAsync("/wrongendpoint", content)
```

### [HttpResponseMessage](src\Ardalis.HttpClientTestExtensions\HttpResponseMessageExtensionMethods.cs)
Expand All @@ -220,6 +232,9 @@ response.EnsureForbidden();
// Assert a response has a status code of 404
response.EnsureNotFound();

// Assert a response has a status code of 405
response.EnsureMethodNotAllowed();

// Assert a response has a given status code
response.Ensure(HttpStatusCode.Created);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Mvc;

namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.MethodNotAllowedEndpoints;

public class NoDelete : EndpointBaseSync
.WithoutRequest
.WithResult<NoContentResult>

{
[Route("/nodelete")]
[AcceptVerbs("GET", "PUT", "POST")]
public override NoContentResult Handle()
{
return NoContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Mvc;

namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.MethodNotAllowedEndpoints;

public class NoGet : EndpointBaseSync
.WithoutRequest
.WithResult<NoContentResult>

{
[Route("/noget")]
[AcceptVerbs("DELETE", "PUT", "POST")]
public override NoContentResult Handle()
{
return NoContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Mvc;

namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.ErrorEndpoints;

public class NoPost : EndpointBaseSync
.WithoutRequest
.WithResult<NoContentResult>

{
[Route("/nopost")]
[AcceptVerbs("DELETE", "PUT", "GET")]
public override NoContentResult Handle()
{
return NoContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Mvc;

namespace Ardalis.HttpClientTestExtensions.Api.Endpoints.ErrorEndpoints;

public class NoPut : EndpointBaseSync
.WithoutRequest
.WithResult<NoContentResult>

{
[Route("/noput")]
[AcceptVerbs("DELETE", "GET", "POST")]
public override NoContentResult Handle()
{
return NoContent();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,12 @@ public async Task DeleteAndRedirectAsync()
var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false });
_ = await client.DeleteAndRedirectAsync("/redirect", "/redirected", _outputHelper);
}

[Fact]
public async Task DeleteAndEnsureMethodNotAllowedAsync()
{
var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false });
_ = await client.DeleteAndEnsureMethodNotAllowedAsync("/nodelete", _outputHelper);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public async Task GetAndEnsureBadRequestAsync()
_ = await _client.GetAndEnsureBadRequestAsync("/badrequest", _outputHelper);
}

[Fact]
public async Task GetAndEnsureMethodNotAllowedAsync()
{
_ = await _client.GetAndEnsureMethodNotAllowedAsync("/noget", _outputHelper);
}

[Fact]
public async Task GetAndRedirectAsync()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,12 @@ public async Task PostAndRedirectAsync()
var client = _factory.CreateClient(new WebApplicationFactoryClientOptions() { AllowAutoRedirect = false });
_ = await client.PostAndRedirectAsync("/redirect", content, "/redirected", _outputHelper);
}

[Fact]
public async Task PostAndEnsureMethodNotAllowedAsync()
{
var dto = new CountryDto { Id = "ESP", Name = "Spain" };
var content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json");
_ = await _client.PostAndEnsureMethodNotAllowedAsync("/nopost", content, _outputHelper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ public async Task PutAndEnsureBadRequestAsync()
_ = await _client.PutAndEnsureBadRequestAsync("/badrequest", content, _outputHelper);
}

[Fact]
public async Task PutAndEnsureMethodNotAllowedAsync()
{
var dto = new CountryDto { Id = SeedData.TestCountry1.Id, Name = "'Merica" };

Check warning on line 81 in tests/Ardalis.HttpClientTestExtensions.Tests/HttpClientPutExtensionMethodsTests.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference assignment.
var content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json");
_ = await _client.PutAndEnsureMethodNotAllowedAsync("/noput", content, _outputHelper);
}

[Fact]
public async Task PutAndRedirectAsync()
{
Expand Down

0 comments on commit 812d861

Please sign in to comment.