Skip to content

Commit 5c17695

Browse files
committed
initial implementation
1 parent 4d90fdd commit 5c17695

File tree

8 files changed

+537
-0
lines changed

8 files changed

+537
-0
lines changed

TestServer.sln

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.32112.339
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServer", "src\TestServer\TestServer.csproj", "{9AF09F0D-5B1B-451C-81FA-75E6FBB55F5E}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer.Tests", "test\TestServer.Tests\TestServer.Tests.csproj", "{AA288AC7-12FA-4D00-87DC-88A5542069C5}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{9AF09F0D-5B1B-451C-81FA-75E6FBB55F5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{9AF09F0D-5B1B-451C-81FA-75E6FBB55F5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{9AF09F0D-5B1B-451C-81FA-75E6FBB55F5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{9AF09F0D-5B1B-451C-81FA-75E6FBB55F5E}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{AA288AC7-12FA-4D00-87DC-88A5542069C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{AA288AC7-12FA-4D00-87DC-88A5542069C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{AA288AC7-12FA-4D00-87DC-88A5542069C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{AA288AC7-12FA-4D00-87DC-88A5542069C5}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {F52F6B90-1394-43AC-87BF-7986DA00F105}
30+
EndGlobalSection
31+
EndGlobal

src/TestServer/Rule.cs

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text.RegularExpressions;
5+
using Microsoft.AspNetCore.Http;
6+
using Microsoft.AspNetCore.Http.Extensions;
7+
8+
namespace TestUtilities
9+
{
10+
public class Rule
11+
{
12+
public IList<Func<HttpRequest, bool>> Predictions { get; set; }
13+
public Action<HttpResponse> Action { get; set; }
14+
public RuleSet RuleSet { get; set; }
15+
16+
public Rule(RuleSet ruleSet)
17+
{
18+
RuleSet = ruleSet;
19+
Predictions = new List<Func<HttpRequest, bool>>();
20+
}
21+
22+
public bool IsValid()
23+
{
24+
return Action != null;
25+
}
26+
27+
public Rule AddRule()
28+
{
29+
if (Action == null)
30+
{
31+
throw new InvalidOperationException("Previous rule not completed");
32+
}
33+
return RuleSet.AddRule();
34+
}
35+
36+
public Rule WhenGet()
37+
{
38+
Predictions.Add((request) =>
39+
{
40+
return request.Method == "GET";
41+
});
42+
return this;
43+
}
44+
45+
public Rule WhenUrlMatch(string pattern)
46+
{
47+
Predictions.Add((request) =>
48+
{
49+
var actualUrl = UriHelper.GetDisplayUrl(request);
50+
return Regex.IsMatch(actualUrl, pattern);
51+
});
52+
return this;
53+
}
54+
55+
public Rule WhenHeaderMatch(string key, string value)
56+
{
57+
Predictions.Add((request) =>
58+
{
59+
if (!request.Headers.TryGetValue(key, out var actual))
60+
{
61+
return false;
62+
}
63+
return actual.Contains(value);
64+
});
65+
return this;
66+
}
67+
68+
public Rule WhenAuthorizationMatch(string token)
69+
{
70+
return WhenHeaderMatch("Authorization", token);
71+
}
72+
73+
public Rule SetBadRequest(string message = "Bad Request")
74+
{
75+
Action = async response =>
76+
{
77+
response.StatusCode = 400;
78+
await response.WriteAsync(message);
79+
};
80+
return this;
81+
}
82+
83+
public Rule SetOkResponse(string output)
84+
{
85+
Action = async response =>
86+
{
87+
await response.WriteAsync(output);
88+
};
89+
return this;
90+
}
91+
}
92+
}

src/TestServer/RuleSet.cs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.AspNetCore.Http;
4+
5+
namespace TestUtilities
6+
{
7+
public class RuleSet
8+
{
9+
public List<Rule> Rules { get; private set; }
10+
public Action<HttpResponse> DefaultAction { get; private set; }
11+
12+
public RuleSet()
13+
{
14+
Rules = new List<Rule>();
15+
DefaultAction = async response =>
16+
{
17+
response.StatusCode = 404;
18+
await response.WriteAsync("Simons says Not Match");
19+
};
20+
}
21+
22+
public Rule AddRule()
23+
{
24+
var rule = new Rule(this);
25+
Rules.Add(rule);
26+
return rule;
27+
}
28+
29+
public RuleSet SetDefaultAction(Action<HttpResponse> action)
30+
{
31+
DefaultAction = action;
32+
return this;
33+
}
34+
}
35+
}

src/TestServer/Startup.cs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using Microsoft.AspNetCore.Builder;
4+
using Microsoft.Extensions.DependencyInjection;
5+
6+
namespace TestUtilities
7+
{
8+
internal class Startup
9+
{
10+
public virtual void ConfigureServices(IServiceCollection services)
11+
{
12+
services.AddRouting();
13+
}
14+
15+
public virtual void Configure(IApplicationBuilder app, RuleSet ruleSet)
16+
{
17+
app.UseRouting();
18+
app.UseEndpoints(endpoints =>
19+
{
20+
endpoints.Map("/", async context =>
21+
{
22+
var matchFound = false;
23+
foreach (var rule in ruleSet.Rules)
24+
{
25+
var match = rule.Predictions.All(prediction => prediction(context.Request));
26+
if (match)
27+
{
28+
await Task.Run(() =>
29+
{
30+
rule.Action(context.Response);
31+
});
32+
matchFound = true;
33+
break;
34+
}
35+
}
36+
if (!matchFound)
37+
{
38+
await Task.Run(() =>
39+
{
40+
ruleSet.DefaultAction(context.Response);
41+
});
42+
}
43+
});
44+
});
45+
}
46+
}
47+
}

src/TestServer/TestServer.cs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Net.Http;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using InternalTestServer = Microsoft.AspNetCore.TestHost.TestServer;
5+
6+
namespace TestUtilities
7+
{
8+
public class TestServer
9+
{
10+
public RuleSet CurrentRuleSet { get; private set; }
11+
12+
public TestServer()
13+
{
14+
CurrentRuleSet = new RuleSet();
15+
}
16+
17+
public HttpClient CreateClient()
18+
{
19+
var builder = new WebHostBuilder()
20+
.ConfigureServices(services =>
21+
{
22+
services.AddSingleton(CurrentRuleSet);
23+
})
24+
.UseStartup<Startup>();
25+
var testServer = new InternalTestServer(builder);
26+
return testServer.CreateClient();
27+
}
28+
}
29+
}

src/TestServer/TestServer.csproj

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
<RootNamespace>TestUtilities</RootNamespace>
6+
<AssemblyName>TestUtilities.TestServer</AssemblyName>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
11+
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
12+
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="2.2.2" />
13+
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.22" />
14+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.22" />
15+
</ItemGroup>
16+
17+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
6+
<IsPackable>false</IsPackable>
7+
8+
<RootNamespace>TestUtilities.Tests</RootNamespace>
9+
10+
<AssemblyName>TestUtilities.TestServer.Tests</AssemblyName>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="NUnit" Version="3.12.0" />
15+
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<ProjectReference Include="..\..\src\TestServer\TestServer.csproj" />
21+
</ItemGroup>
22+
23+
</Project>

0 commit comments

Comments
 (0)