Skip to content

Commit a7ca1ce

Browse files
authored
Merge pull request #28 from MrDave1999/sample/add-tests
test: Add integration test project for samples
2 parents e180602 + eeb0e0c commit a7ca1ce

File tree

16 files changed

+265
-7
lines changed

16 files changed

+265
-7
lines changed

.github/workflows/dotnetcore.yml

+7-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,10 @@ jobs:
2222
with:
2323
dotnet-version: ${{ matrix.dotnet-version }}
2424
- name: Test
25-
run: dotnet test ./tests/CPlugin.Net/CPlugin.Net.Tests.csproj
25+
run: |
26+
dotnet test ./tests/CPlugin.Net/CPlugin.Net.Tests.csproj
27+
dotnet build ./samples/Plugins/AppointmentPlugin/Example.AppointmentPlugin.csproj
28+
dotnet build ./samples/Plugins/PersonPlugin/Example.PersonPlugin.csproj
29+
dotnet build ./samples/Plugins/JsonPlugin/Example.JsonPlugin.csproj
30+
dotnet build ./samples/Plugins/OldJsonPlugin/Example.OldJsonPlugin.csproj
31+
dotnet test ./samples/Test/Example.Test.csproj

CPlugin.Net.sln

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.AppointmentPlugin",
2525
EndProject
2626
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.PersonPlugin", "samples\Plugins\PersonPlugin\Example.PersonPlugin.csproj", "{18534944-583B-4924-AC5B-E0655FD92AAC}"
2727
EndProject
28+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.Test", "samples\Test\Example.Test.csproj", "{1E64908D-DC48-4B83-BB25-CF36821EB37F}"
29+
EndProject
2830
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProject.JsonPlugin", "tests\Plugins\TestProject.JsonPlugin\TestProject.JsonPlugin.csproj", "{0F27C776-F284-4C94-86C9-0FF089245E13}"
2931
EndProject
3032
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProject.OldJsonPlugin", "tests\Plugins\TestProject.OldJsonPlugin\TestProject.OldJsonPlugin.csproj", "{BCE8FA91-AF31-49DD-BED8-E60A46915400}"
@@ -120,6 +122,10 @@ Global
120122
{0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
121123
{0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
122124
{0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Release|Any CPU.Build.0 = Release|Any CPU
125+
{1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
126+
{1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.Build.0 = Debug|Any CPU
127+
{1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.ActiveCfg = Release|Any CPU
128+
{1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.Build.0 = Release|Any CPU
123129
EndGlobalSection
124130
GlobalSection(SolutionProperties) = preSolution
125131
HideSolutionNode = FALSE

samples/Contracts/ICommand.cs

+1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ public interface ICommand
44
{
55
string Name { get; }
66
string Description { get; }
7+
string Version { get; }
78
int Execute();
89
}

samples/HostApplications/WebApi/Controllers/PeopleController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ public class PeopleController
1111
public Result<List<Person>> GetAll() => Result.Success(_persons);
1212

1313
[HttpPost]
14-
public Result Create() => Result.Success();
14+
public ActionResult<Result> Create() => Result.CreatedResource().ToActionResult();
1515
}

samples/HostApplications/WebApi/Program.cs

+2
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@
4444
app.MapControllers();
4545

4646
app.Run();
47+
48+
public partial class Program { }

samples/Plugins/AppointmentPlugin/Startup.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ public void ConfigureServices(IServiceCollection services)
1515
{
1616
new()
1717
{
18-
Id = Guid.NewGuid().ToString(),
18+
Id = "16e299b4-a6dc-4aa3-a52c-7dae088241e6",
1919
DoctorName = "Bob",
2020
PatientName = "Alice",
2121
Date = new DateOnly(2023, 01, 01)
2222
},
2323
new()
2424
{
25-
Id = Guid.NewGuid().ToString(),
25+
Id = "5dace456-13d9-42c5-92ea-89869ac44b5c",
2626
DoctorName = "Dave",
2727
PatientName = "Martin",
2828
Date = new DateOnly(2023, 01, 05)
2929
},
3030
new()
3131
{
32-
Id = Guid.NewGuid().ToString(),
32+
Id = "4575709f-cb5d-4919-9fc2-4afcf5f3c431",
3333
DoctorName = "Steven",
3434
PatientName = "Smith",
3535
Date = new DateOnly(2023, 01, 10)

samples/Plugins/JsonPlugin/CreateJson.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public class CreateJson : ICommand
66
{
77
public string Name => "json";
88
public string Description => "Outputs JSON value.";
9+
public string Version => typeof(JsonConvert).Assembly.FullName;
910

1011
private class Info
1112
{

samples/Plugins/OldJsonPlugin/CreateJson.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public class CreateJson : ICommand
66
{
77
public string Name => "oldjson";
88
public string Description => "Outputs JSON value.";
9+
public string Version => typeof(JsonConvert).Assembly.FullName;
910

1011
private class Info
1112
{

samples/Plugins/PersonPlugin/Example.PersonPlugin.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</ItemGroup>
1212

1313
<ItemGroup>
14-
<PackageReference Include="SimpleResults" Version="0.3.0-alpha" />
14+
<PackageReference Include="SimpleResults.AspNetCore" Version="0.3.0-alpha" />
1515
</ItemGroup>
1616

1717
</Project>

samples/Plugins/PersonPlugin/PersonController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ public Result<IEnumerable<Person>> GetAll(IPersonService service)
99
=> service.GetAll();
1010

1111
[HttpPost]
12-
public Result Create() => Result.Success();
12+
public ActionResult<Result> Create() => Result.CreatedResource().ToActionResult();
1313
}

samples/Test/Example.Test.csproj

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<IsPackable>false</IsPackable>
5+
<IsTestProject>true</IsTestProject>
6+
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
11+
<PackageReference Include="FluentAssertions" />
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" />
13+
<PackageReference Include="NUnit" />
14+
<PackageReference Include="NUnit3TestAdapter" />
15+
<PackageReference Include="NUnit.Analyzers" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\HostApplications\WebApi\Example.HostWebApi.csproj" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<!-- Copy the plugins directory from Example.HostWebApi to the output directory of Example.Test. -->
24+
<Content
25+
Include="..\HostApplications\WebApi\bin\$(Configuration)\$(TargetFramework)\plugins\**"
26+
CopyToOutputDirectory="PreserveNewest"
27+
TargetPath="plugins\%(RecursiveDir)\%(Filename)%(Extension)"
28+
/>
29+
30+
<!-- Copy the plugins directory from Example.HostConsoleApp to the output directory of Example.Test. -->
31+
<Content
32+
Include="..\HostApplications\ConsoleApp\bin\$(Configuration)\$(TargetFramework)\plugins\**"
33+
CopyToOutputDirectory="PreserveNewest"
34+
TargetPath="plugins\%(RecursiveDir)\%(Filename)%(Extension)"
35+
/>
36+
</ItemGroup>
37+
38+
</Project>

samples/Test/GlobalUsings.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global using NUnit.Framework;
2+
global using FluentAssertions;
3+
global using Microsoft.AspNetCore.Mvc.Testing;
4+
global using SimpleResults;
5+
global using System.Net;
6+
global using Example.WebApi;
7+
global using CPlugin.Net;
8+
global using Example.Contracts;

samples/Test/PluginLoaderTest.cs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
namespace Example.Test;
2+
3+
public class PluginLoaderTest
4+
{
5+
private class GetPluginInfo
6+
{
7+
public string Name { get; set; }
8+
public string Description { get; set; }
9+
public string Version { get; set; }
10+
}
11+
12+
[Test]
13+
public void Load_WhenPluginsAreFound_ShouldBeLoadedIntoMemory()
14+
{
15+
// Arrange
16+
var plugins =
17+
"""
18+
Example.JsonPlugin.dll
19+
Example.OldJsonPlugin.dll
20+
""";
21+
Environment.SetEnvironmentVariable("PLUGINS", plugins);
22+
var envConfiguration = new CPluginEnvConfiguration();
23+
var expectedInfo = new GetPluginInfo[]
24+
{
25+
new()
26+
{
27+
Name = "json",
28+
Description = "Outputs JSON value.",
29+
Version = "Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"
30+
},
31+
new()
32+
{
33+
Name = "oldjson",
34+
Description = "Outputs JSON value.",
35+
Version = "Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"
36+
}
37+
};
38+
39+
// Act
40+
PluginLoader.Load(envConfiguration);
41+
var commands = TypeFinder.FindSubtypesOf<ICommand>();
42+
var actualInfo = commands.Select(command => new GetPluginInfo
43+
{
44+
Name = command.Name,
45+
Description = command.Description,
46+
Version = command.Version
47+
}).ToArray();
48+
49+
// Assert
50+
actualInfo.Should().BeEquivalentTo(expectedInfo);
51+
}
52+
}

samples/Test/WebApi/Get.cs

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
namespace Example.Test.WebApi;
2+
3+
public class Get
4+
{
5+
[Test]
6+
public async Task Get_WhenAppointmentsAreObtained_ShouldReturnsHttpStatusCodeOk()
7+
{
8+
// Arrange
9+
using var factory = new WebApplicationFactory<Program>();
10+
var client = factory.CreateClient();
11+
int expectedAppointments = 3;
12+
13+
// Act
14+
var httpResponse = await client.GetAsync("/Appointment");
15+
var result = await httpResponse
16+
.Content
17+
.ReadFromJsonAsync<ListedResult<GetAppointmentResponse>>();
18+
19+
// Asserts
20+
httpResponse.StatusCode.Should().Be(HttpStatusCode.OK);
21+
result.IsSuccess.Should().BeTrue();
22+
result.Data.Should().HaveCount(expectedAppointments);
23+
}
24+
25+
[Test]
26+
public async Task Get_WhenAppointmentIsObtained_ShouldReturnsHttpStatusCodeOk()
27+
{
28+
// Arrange
29+
using var factory = new WebApplicationFactory<Program>();
30+
var client = factory.CreateClient();
31+
var requestUri = "/Appointment/5dace456-13d9-42c5-92ea-89869ac44b5c";
32+
33+
// Act
34+
var httpResponse = await client.GetAsync(requestUri);
35+
var result = await httpResponse
36+
.Content
37+
.ReadFromJsonAsync<Result<GetAppointmentResponse>>();
38+
39+
// Asserts
40+
httpResponse.StatusCode.Should().Be(HttpStatusCode.OK);
41+
result.IsSuccess.Should().BeTrue();
42+
result.Data.Should().NotBeNull();
43+
}
44+
45+
[Test]
46+
public async Task Get_WhenAppointmentIsNotFound_ShouldReturnsHttpStatusCodeNotFound()
47+
{
48+
// Arrange
49+
using var factory = new WebApplicationFactory<Program>();
50+
var client = factory.CreateClient();
51+
var requestUri = "/Appointment/5dace456";
52+
53+
// Act
54+
var httpResponse = await client.GetAsync(requestUri);
55+
var result = await httpResponse
56+
.Content
57+
.ReadFromJsonAsync<Result<GetAppointmentResponse>>();
58+
59+
// Asserts
60+
httpResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
61+
result.IsSuccess.Should().BeFalse();
62+
result.Data.Should().BeNull();
63+
}
64+
65+
[TestCase("/People")]
66+
[TestCase("/Person")]
67+
public async Task Get_WhenPersonsAreObtained_ShouldReturnsHttpStatusCodeOk(string requestUri)
68+
{
69+
// Arrange
70+
using var factory = new WebApplicationFactory<Program>();
71+
var client = factory.CreateClient();
72+
int expectedPersons = 3;
73+
74+
// Act
75+
var httpResponse = await client.GetAsync(requestUri);
76+
var result = await httpResponse
77+
.Content
78+
.ReadFromJsonAsync<Result<IEnumerable<GetPersonResponse>>>();
79+
80+
// Asserts
81+
httpResponse.StatusCode.Should().Be(HttpStatusCode.OK);
82+
result.IsSuccess.Should().BeTrue();
83+
result.Data.Should().HaveCount(expectedPersons);
84+
}
85+
86+
[Test]
87+
public async Task Get_WhenWeatherForecastAreObtained_ShouldReturnsHttpStatusCodeOk()
88+
{
89+
// Arrange
90+
using var factory = new WebApplicationFactory<Program>();
91+
var client = factory.CreateClient();
92+
int expectedWeatherForecast = 5;
93+
94+
// Act
95+
var httpResponse = await client.GetAsync("/WeatherForecast");
96+
var result = await httpResponse
97+
.Content
98+
.ReadFromJsonAsync<ListedResult<WeatherForecast>>();
99+
100+
// Asserts
101+
httpResponse.StatusCode.Should().Be(HttpStatusCode.OK);
102+
result.IsSuccess.Should().BeTrue();
103+
result.Data.Should().HaveCount(expectedWeatherForecast);
104+
}
105+
}

samples/Test/WebApi/Models.cs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Example.Test.WebApi;
2+
3+
public class GetAppointmentResponse
4+
{
5+
public string Id { get; set; }
6+
public string DoctorName { get; set; }
7+
public string PatientName { get; set; }
8+
}
9+
10+
public class GetPersonResponse
11+
{
12+
public int Id { get; set; }
13+
public string Name { get; set; }
14+
public string Document { get; set; }
15+
}

samples/Test/WebApi/Post.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace Example.Test.WebApi;
2+
3+
public class Post
4+
{
5+
[TestCase("/Person")]
6+
[TestCase("/People")]
7+
public async Task Post_WhenPersonIsCreated_ShouldReturnsHttpStatusCodeCreated(string requestUri)
8+
{
9+
// Arrange
10+
using var factory = new WebApplicationFactory<Program>();
11+
var client = factory.CreateClient();
12+
13+
// Act
14+
var httpResponse = await client.PostAsJsonAsync(requestUri, new {});
15+
var result = await httpResponse
16+
.Content
17+
.ReadFromJsonAsync<Result>();
18+
19+
// Asserts
20+
httpResponse.StatusCode.Should().Be(HttpStatusCode.Created);
21+
result.IsSuccess.Should().BeTrue();
22+
}
23+
}

0 commit comments

Comments
 (0)