Skip to content

Commit

Permalink
Implement additional functionality (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaliumhexacyanoferrat authored Dec 3, 2021
1 parent 3e89461 commit ef3aba3
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 6 deletions.
2 changes: 2 additions & 0 deletions MockH.Tests/MockH.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

<ItemGroup>

<PackageReference Include="GenHTTP.Modules.DirectoryBrowsing" Version="6.2.0" />

<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />

<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
Expand Down
41 changes: 41 additions & 0 deletions MockH.Tests/RedirectTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;

namespace MockH.Tests
{

[TestClass]
public class RedirectTests : ServerTest
{

[TestMethod]
public async Task RulesCanRedirectTemporarily()
{
using var server = MockServer.Run
(
On.Get().Redirect("https://www.google.de")
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.TemporaryRedirect, response.StatusCode);
Assert.AreEqual(new Uri("https://www.google.de"), response.Headers.Location);
}

[TestMethod]
public async Task RulesCanRedirectPermanently()
{
using var server = MockServer.Run
(
On.Get().Redirect("https://www.google.de", temporary: false)
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.Moved, response.StatusCode);
Assert.AreEqual(new Uri("https://www.google.de"), response.Headers.Location);
}

}

}
27 changes: 27 additions & 0 deletions MockH.Tests/RespondTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using GenHTTP.Api.Protocol;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;

namespace MockH.Tests
{

[TestClass]
public class RespondTests : ServerTest
{

[TestMethod]
public async Task BasicResponse()
{
using var server = MockServer.Run
(
On.Get().Respond(ResponseStatus.InternalServerError)
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode);
}

}

}
128 changes: 128 additions & 0 deletions MockH.Tests/RunTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using GenHTTP.Api.Protocol;
using GenHTTP.Modules.DirectoryBrowsing;
using GenHTTP.Modules.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;

namespace MockH.Tests
{

[TestClass]
public class RunTests : ServerTest
{

[TestMethod]
public async Task TestConstant()
{
using var server = MockServer.Run
(
On.Get().Run(() => 42)
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("42", await response.Content.ReadAsStringAsync());
}

private record MyClass(int IntValue, string StringValue);

[TestMethod]
public async Task TestJson()
{
using var server = MockServer.Run
(
On.Get().Run(() => new MyClass(42, "The answer"))
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("{\"intValue\":42,\"stringValue\":\"The answer\"}", await response.Content.ReadAsStringAsync());
}

[TestMethod]
public async Task TestQuery()
{
using var server = MockServer.Run
(
On.Get().Run((int i) => i + 1)
);

using var response = await GetAsync(server, "/?i=1");

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("2", await response.Content.ReadAsStringAsync());
}

[TestMethod]
public async Task TestPath()
{
using var server = MockServer.Run
(
On.Get("/increment/:i").Run((int i) => i + 1)
);

using var response = await GetAsync(server, "/increment/1");

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("2", await response.Content.ReadAsStringAsync());
}

[TestMethod]
public async Task TestPost()
{
using var server = MockServer.Run
(
On.Post().Run((MyClass body) => body)
);

using var response = await PostAsync(server, "{\"intValue\":42,\"stringValue\":\"The answer\"}");

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("{\"intValue\":42,\"stringValue\":\"The answer\"}", await response.Content.ReadAsStringAsync());
}

[TestMethod]
public async Task TestStream()
{
using var server = MockServer.Run
(
On.Post().Run((Stream body) => body.Length)
);

using var response = await PostAsync(server, "{\"intValue\":42,\"stringValue\":\"The answer\"}");

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual("42" /* :D */, await response.Content.ReadAsStringAsync());
}

[TestMethod]
public async Task TestRequest()
{
using var server = MockServer.Run
(
On.Get().Run((IRequest request) => request.Respond().Status(ResponseStatus.BadRequest))
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
}

[TestMethod]
public async Task TestHandler()
{
using var server = MockServer.Run
(
On.Get().Run(() => Listing.From(ResourceTree.FromDirectory("./")))
);

using var response = await GetAsync(server);

Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}

}

}
17 changes: 16 additions & 1 deletion MockH.Tests/ServerTest.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;

using MockH.Environment;
using System.Net.Http.Json;

namespace MockH.Tests
{

public abstract class ServerTest
{
protected HttpClient _Client = new();
protected HttpClient _Client = new(new HttpClientHandler()
{
AllowAutoRedirect = false
});

protected async ValueTask<string> GetStringAsync(Server server, string? path = null) => await _Client.GetStringAsync(server.Url(path));

protected async ValueTask<HttpResponseMessage> GetAsync(Server server, string? path = null) => await _Client.GetAsync(server.Url(path));

protected async ValueTask<HttpResponseMessage> PostAsync(Server server, string value, string? path = null)
{
var content = new StringContent(value);

content.Headers.ContentType = new("application/json");

return await _Client.PostAsync(server.Url(path), content);
}

[TestCleanup]
public void Cleanup()
Expand Down
7 changes: 6 additions & 1 deletion MockH.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ VisualStudioVersion = 17.0.31912.275
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MockH", "MockH\MockH.csproj", "{69AB1471-7E7D-4C76-BDD8-58CA8369649F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MockH.Tests", "MockH.Tests\MockH.Tests.csproj", "{C5EA4883-2BBE-4F46-AC99-465DF6895958}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MockH.Tests", "MockH.Tests\MockH.Tests.csproj", "{C5EA4883-2BBE-4F46-AC99-465DF6895958}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{83377AA8-18D5-4CFF-9AE6-B11070952B2F}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
8 changes: 8 additions & 0 deletions MockH/Builder/IncompleteRule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using GenHTTP.Api.Protocol;

using Basics = GenHTTP.Modules.Basics;

namespace MockH.Builder
{

Expand Down Expand Up @@ -31,6 +33,12 @@ public IncompleteRule(HashSet<FlexibleRequestMethod> methods, string? path)

public Rule Return<T>(T data) => new(Methods, Path, () => data);

public Rule Redirect(string location, bool temporary = true) => new(Methods, Path, (IRequest request) => Basics.Redirect.To(location).Mode(temporary));

public Rule Run(Delegate action) => new(Methods, Path, action);

public Rule Respond(ResponseStatus status) => new(Methods, Path, (IRequest request) => request.Respond().Status(status).Build());

#endregion

}
Expand Down
4 changes: 2 additions & 2 deletions MockH/MockH.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@

<None Include="..\LICENSE" Pack="true" PackagePath="\" />

<PackageReference Include="GenHTTP.Core" Version="6.1.0" />
<PackageReference Include="GenHTTP.Core" Version="6.2.0" />

<PackageReference Include="GenHTTP.Modules.Functional" Version="6.1.0" />
<PackageReference Include="GenHTTP.Modules.Functional" Version="6.2.0" />

<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />

Expand Down
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,71 @@ This library allows to mock HTTP responses for integration and acceptance tests

- Fast and thread safe
- Only a few dependencies
- No configuration needed
- Does not interfer with Kestrel or ASP.NET
- Independent from the testing framework

## Usage

```
```csharp
using MockH;

[TestMethod]
public async Task TestSomething()
{
using var server = MockServer.Run
(
On.Get("/users/1").Return(new User(...))
On.Get("/users/1").Return(new User(...)),
On.Get("/users/2").Respond(ResponseStatus.NoContent)
);

// access the server in your code via HTTP
using var client = new HttpClient();

await client.GetStringAsync(server.Url("/users/1"));
}
```

## Basic Usage

```csharp
// return a specific status code
On.Get("/ifail").Respond(ResponseStatus.InternalServerError);

// redirect the client
On.Get().Redirect("https://github.com");

// execute logic and return some simple text value
On.Get().Run(() => 42);

// execute logic and return some JSON
private record MyClass(int IntValue, string StringValue);

On.Get().Run(() => new MyClass(42, "The answer"));

// execute logic asynchronously
On.Get().Run(async () => await ...);

// access query parameters (GET /increment?=1)
On.Get("/increment").Run((int i) => i + 1);

// access path parameters (GET /increment/1)
On.Get("/increment/:i").Run((int i) => i + 1);

// access request body
On.Post().Run((MyClass body) => body);

// access request body as stream
On.Post().Run((Stream body) => body.Length);
```

## Advanced Usage

```csharp
// directly access request and response
On.Get().Run((IRequest request) => request.Respond().Status(ResponseStatus.BadRequest));

// return a handler provided by the GenHTTP framework, e.g. a website (see https://genhttp.org/documentation/content/)
// can be useful if you want to test some kind of website crawler
On.Get().Run(() => Listing.From(ResourceTree.FromDirectory("/var/www")));
```

0 comments on commit ef3aba3

Please sign in to comment.