Skip to content

Commit 51550ed

Browse files
feat: implement demo tests
1 parent 74ff886 commit 51550ed

File tree

11 files changed

+374
-3
lines changed

11 files changed

+374
-3
lines changed

CanBeYours.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "src\4-Build\Build.
2525
EndProject
2626
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "src\2-Clients\Api\Api.csproj", "{881CF5E2-F99A-47EF-9538-CA84E574716B}"
2727
EndProject
28+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.Tests.Unit", "src\3-Tests\Application.Tests.Unit\Application.Tests.Unit.csproj", "{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663}"
29+
EndProject
30+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.Tests.Integration", "src\3-Tests\Application.Tests.Integration\Application.Tests.Integration.csproj", "{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2}"
31+
EndProject
2832
Global
2933
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3034
Debug|Any CPU = Debug|Any CPU
@@ -57,6 +61,14 @@ Global
5761
{881CF5E2-F99A-47EF-9538-CA84E574716B}.Debug|Any CPU.Build.0 = Debug|Any CPU
5862
{881CF5E2-F99A-47EF-9538-CA84E574716B}.Release|Any CPU.ActiveCfg = Release|Any CPU
5963
{881CF5E2-F99A-47EF-9538-CA84E574716B}.Release|Any CPU.Build.0 = Release|Any CPU
64+
{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65+
{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663}.Debug|Any CPU.Build.0 = Debug|Any CPU
66+
{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663}.Release|Any CPU.ActiveCfg = Release|Any CPU
67+
{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663}.Release|Any CPU.Build.0 = Release|Any CPU
68+
{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69+
{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
70+
{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
71+
{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2}.Release|Any CPU.Build.0 = Release|Any CPU
6072
EndGlobalSection
6173
GlobalSection(SolutionProperties) = preSolution
6274
HideSolutionNode = FALSE
@@ -69,6 +81,8 @@ Global
6981
{9FF64B62-92A1-4037-BF55-3FD88C51D1CD} = {2A8496DF-F400-4F3A-BDBE-CD05C566EBE3}
7082
{D8F45352-374F-4FF1-A405-FD38F61E7BC4} = {7112C95C-B504-4540-B382-7004E7C9B60E}
7183
{881CF5E2-F99A-47EF-9538-CA84E574716B} = {32AFCA52-3D74-4C1F-9BE4-AB2C6A9B471A}
84+
{4D3E3ACB-A5E9-4B41-9566-9991E9C1D663} = {FD02FBB7-69CD-4F52-9033-43B17B986D31}
85+
{AA7881E4-46A2-4157-B3A5-2F0F4CDA76F2} = {FD02FBB7-69CD-4F52-9033-43B17B986D31}
7286
EndGlobalSection
7387
GlobalSection(ExtensibilityGlobals) = postSolution
7488
SolutionGuid = {1B69CCCE-CED3-4813-AE80-2F1A7B0D9691}

src/1-Libraries/Application/Application.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,5 @@
2020
<ItemGroup>
2121
<ProjectReference Include="..\Core\Core.csproj" />
2222
</ItemGroup>
23-
<ItemGroup>
24-
<Folder Include="UseCases\" />
25-
</ItemGroup>
23+
2624
</Project>

src/1-Libraries/Infrastructure/DbContext/MainDbContext.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,13 @@ protected override void CreateIndexes()
2020
)
2121
);
2222
}
23+
24+
public void DropTestDatabase()
25+
{
26+
// Only drop the database if it starts with "Test_" to avoid dropping production databases.
27+
if (!_mongoDbSettings.DatabaseName.StartsWith("Test_"))
28+
return;
29+
30+
_client.DropDatabase(_mongoDbSettings.DatabaseName);
31+
}
2332
}

src/1-Libraries/Infrastructure/Startup.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public static void UseInfrastructureModule(this IServiceProvider serviceProvider
2828
serviceProvider.SeedPermissions();
2929
}
3030

31+
public static void DropTestDatabase(this IServiceProvider serviceProvider)
32+
{
33+
using var serviceScope = serviceProvider.CreateScope();
34+
var dbContext = serviceScope.ServiceProvider.GetService<MainDbContext>();
35+
dbContext.DropTestDatabase();
36+
}
37+
3138
private static void AddMongoDbContext(this IServiceCollection services)
3239
{
3340
services.AddScoped<MainDbContext>();
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<AssemblyName>CanBeYours.Application.Tests.Integration</AssemblyName>
7+
<RootNamespace>CanBeYours.Application.Tests.Integration</RootNamespace>
8+
<Nullable>enable</Nullable>
9+
<IsPackable>false</IsPackable>
10+
<IsTestProject>true</IsTestProject>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
16+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
17+
<PackageReference Include="CodeBlock.DevKit.Test" Version="1.3.7" />
18+
<PackageReference Include="CodeBlock.DevKit.Clients.AdminPanel" Version="1.3.7" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="..\..\1-Libraries\Application\Application.csproj" />
23+
<ProjectReference Include="..\..\1-Libraries\Infrastructure\Infrastructure.csproj" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<Using Include="Xunit" />
28+
</ItemGroup>
29+
30+
<Target Name="CopyConfig" AfterTargets="AfterBuild">
31+
<Copy SourceFiles="..\..\2-Clients\AdminPanel\appsettings.json" DestinationFolder="$(OutDir)" />
32+
<Copy SourceFiles="..\..\2-Clients\AdminPanel\appsettings.Development.json" DestinationFolder="$(OutDir)" />
33+
</Target>
34+
35+
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace CanBeYours.Application.Tests.Integration.Fixtures;
2+
3+
/// <summary>
4+
///
5+
/// </summary>
6+
[CollectionDefinition(nameof(DemoThingsCollectionFixture))]
7+
public class DemoThingCollectionFixtureDefinition : ICollectionFixture<DemoThingsCollectionFixture>
8+
{
9+
// This class has no code, and is never created. Its purpose is simply
10+
// to be the place to apply [CollectionDefinition] and all the
11+
// ICollectionFixture<> interfaces.
12+
}
13+
14+
/// <summary>
15+
///
16+
/// </summary>
17+
public class DemoThingsCollectionFixture : TestsBaseFixture
18+
{
19+
public DemoThingsCollectionFixture()
20+
: base(dbNameSuffix: nameof(DemoThingsCollectionFixture)) { }
21+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using AutoMapper;
2+
using CanBeYours.Core.Domain.DemoThings;
3+
using CanBeYours.Infrastructure;
4+
using CodeBlock.DevKit.Application.Srvices;
5+
using CodeBlock.DevKit.Clients.AdminPanel;
6+
using CodeBlock.DevKit.Test.TestBase;
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.DependencyInjection.Extensions;
11+
using Microsoft.Extensions.Logging;
12+
using NSubstitute;
13+
14+
namespace CanBeYours.Application.Tests.Integration.Fixtures;
15+
16+
public abstract class TestsBaseFixture : IntegrationTestsBase
17+
{
18+
public readonly IRequestDispatcher _requestDispatcher;
19+
public readonly IMapper _mapper;
20+
public readonly IDemoThingRepository _demoThingRepository;
21+
public readonly ICurrentUser _currentUser;
22+
public readonly ILogger _logger;
23+
24+
protected TestsBaseFixture(string dbNameSuffix)
25+
: base(dbNameSuffix)
26+
{
27+
_demoThingRepository = GetRequiredService<IDemoThingRepository>();
28+
_mapper = GetRequiredService<IMapper>();
29+
_currentUser = GetRequiredService<ICurrentUser>();
30+
_logger = GetRequiredService<ILogger>();
31+
_requestDispatcher = Substitute.For<IRequestDispatcher>();
32+
}
33+
34+
/// <summary>
35+
///
36+
/// </summary>
37+
public override void InitialDatabase() { }
38+
39+
/// <summary>
40+
///
41+
/// </summary>
42+
public override void DropDatabase()
43+
{
44+
_serviceProvider.DropTestDatabase();
45+
}
46+
47+
/// <summary>
48+
///
49+
/// </summary>
50+
public async Task SeedDemoThingAsync(DemoThing demoThing)
51+
{
52+
await _demoThingRepository.AddAsync(demoThing);
53+
}
54+
55+
/// <summary>
56+
///
57+
/// </summary>
58+
public async Task<DemoThing> GetDemoThingAsync(string id)
59+
{
60+
return await _demoThingRepository.GetByIdAsync(id);
61+
}
62+
63+
/// <summary>
64+
///
65+
/// </summary>
66+
public override IServiceProvider GetServiceProvider(string dbNameSuffix)
67+
{
68+
var services = new ServiceCollection();
69+
70+
var configuration = new ConfigurationBuilder()
71+
//Copy from AdminPanel during the build event
72+
.AddJsonFile("appsettings.json", reloadOnChange: true, optional: false)
73+
.AddJsonFile("appsettings.Development.json", optional: true)
74+
.AddInMemoryCollection([new KeyValuePair<string, string?>("MongoDB:DatabaseName", $"Test_DemoThings_DB_{dbNameSuffix}")])
75+
.Build();
76+
77+
services.AddSingleton<IConfiguration>(provider =>
78+
{
79+
return configuration;
80+
});
81+
82+
var builder = WebApplication.CreateBuilder();
83+
84+
builder.Services.Add(services);
85+
86+
builder.AddAdminPanelClientModule(typeof(TestsBaseFixture));
87+
builder.Services.AddInfrastructureModule();
88+
89+
return services.BuildServiceProvider();
90+
}
91+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using CanBeYours.Application.Tests.Integration.Fixtures;
2+
using CanBeYours.Core.Domain.DemoThings;
3+
using FluentAssertions;
4+
5+
namespace CanBeYours.Application.Tests.Integration.UseCases.DemoThings;
6+
7+
[Collection(nameof(DemoThingsCollectionFixture))]
8+
public class CreateDemoThingTests
9+
{
10+
private readonly DemoThingsCollectionFixture _fixture;
11+
12+
public CreateDemoThingTests(DemoThingsCollectionFixture fixture)
13+
{
14+
_fixture = fixture;
15+
}
16+
17+
[Fact]
18+
public async Task DemoThing_is_added()
19+
{
20+
//Arrange
21+
var request = new CreateDemoThingRequest(name: "Test Name", description: "Test Description", type: DemoThingType.DemoType1);
22+
var createDemoThingUseCase = new CreateDemoThingUseCase(
23+
_fixture._demoThingRepository,
24+
_fixture._requestDispatcher,
25+
_fixture._logger,
26+
_fixture._currentUser
27+
);
28+
29+
//Act
30+
var result = await createDemoThingUseCase.Handle(request, CancellationToken.None);
31+
32+
//Assert
33+
result.EntityId.Should().NotBeNull();
34+
}
35+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
15+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
16+
<PackageReference Include="CodeBlock.DevKit.Test" Version="1.3.7" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<ProjectReference Include="..\..\1-Libraries\Application\Application.csproj" />
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<Using Include="Xunit" />
25+
</ItemGroup>
26+
27+
</Project>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using CanBeYours.Core.Domain.DemoThings;
2+
using Castle.Core.Logging;
3+
using CodeBlock.DevKit.Application.Srvices;
4+
using CodeBlock.DevKit.Test.TestBase;
5+
using NSubstitute;
6+
7+
namespace Application.Tests.Unit.Fixtures;
8+
9+
public abstract class TestsBaseFixture : UnitTestsBase
10+
{
11+
protected IRequestDispatcher? RequestDispatcher;
12+
protected ILogger? Logger;
13+
protected IDemoThingRepository? DemoThingRepository;
14+
protected List<DemoThing> DemoThings = new List<DemoThing>();
15+
protected ICurrentUser? CurrentUser;
16+
17+
protected override void FixtureSetup()
18+
{
19+
CommonFixtureSetup();
20+
21+
TestClassFixtureSetup();
22+
}
23+
24+
private void CommonFixtureSetup()
25+
{
26+
RequestDispatcher = Substitute.For<IRequestDispatcher>();
27+
Logger = Substitute.For<ILogger>();
28+
CurrentUser = Substitute.For<ICurrentUser>();
29+
30+
DemoThings = GenerateDemoThingsList();
31+
32+
DemoThingRepository = Substitute.For<IDemoThingRepository>();
33+
DemoThingRepository
34+
.GetByIdAsync(Arg.Is<string>(x => DemoThings.Any(o => o.Id == x)))
35+
.Returns(args => DemoThings.First(u => u.Id == (string)args[0]));
36+
DemoThingRepository
37+
.AddAsync(Arg.Any<DemoThing>())
38+
.Returns(args =>
39+
{
40+
DemoThings.Add((DemoThing)args[0]);
41+
return Task.CompletedTask;
42+
});
43+
DemoThingRepository
44+
.UpdateAsync(Arg.Is<DemoThing>(x => DemoThings.Any(o => o.Id == x.Id)))
45+
.Returns(args =>
46+
{
47+
var existDemoThing = DemoThings.FirstOrDefault(u => u.Id == ((DemoThing)args[0]).Id);
48+
if (existDemoThing != null)
49+
{
50+
DemoThings.Remove(existDemoThing);
51+
DemoThings.Add((DemoThing)args[0]);
52+
}
53+
54+
return Task.CompletedTask;
55+
});
56+
57+
//DemoThingRepository
58+
// .ConcurrencySafeUpdateAsync(Arg.Is<DemoThing>(x => DemoThings.Any(o => o.Id == x.Id)), Arg.Is<string>(x => x.Any()))
59+
// .Returns(args =>
60+
// {
61+
// var existDemoThing = DemoThings.FirstOrDefault(u => u.Id == ((DemoThing)args[0]).Id && u.Version == (string)args[1]);
62+
// if (existDemoThing != null)
63+
// {
64+
// DemoThings.Remove(existDemoThing);
65+
// DemoThings.Add((DemoThing)args[0]);
66+
// }
67+
68+
// return Task.CompletedTask;
69+
// });
70+
71+
DemoThingRepository
72+
.DeleteAsync(Arg.Is<string>(x => DemoThings.Any(o => o.Id == x)))
73+
.Returns(args =>
74+
{
75+
var demoThing = DemoThings.FirstOrDefault(u => u.Id == (string)args[0]);
76+
if (demoThing != null)
77+
DemoThings.Remove(demoThing);
78+
79+
return Task.CompletedTask;
80+
});
81+
}
82+
83+
/// <summary>
84+
/// Each test class should setup its own fixture
85+
/// </summary>
86+
protected abstract void TestClassFixtureSetup();
87+
88+
/// <summary>
89+
///
90+
/// </summary>
91+
private List<DemoThing> GenerateDemoThingsList()
92+
{
93+
return new List<DemoThing>
94+
{
95+
DemoThing.Create("Demo Thing 1", "Description 1", DemoThingType.DemoType1, "User1"),
96+
DemoThing.Create("Demo Thing 2", "Description 2", DemoThingType.DemoType2, "User2"),
97+
DemoThing.Create("Demo Thing 3", "Description 3", DemoThingType.DemoType3, "User3"),
98+
};
99+
}
100+
}

0 commit comments

Comments
 (0)