From cd2ec646fd98fe0fd1d27a5e2013fe3a36b52bc7 Mon Sep 17 00:00:00 2001 From: eelke Date: Sun, 22 Feb 2026 08:21:54 +0100 Subject: [PATCH] Add some tests --- .../Services/ClientServiceTests.cs | 154 ++++++++++++++++++ .../Services/RealmServiceTests.cs | 39 ++++- IdentityShroud.sln.DotSettings.user | 5 +- 3 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 IdentityShroud.Core.Tests/Services/ClientServiceTests.cs diff --git a/IdentityShroud.Core.Tests/Services/ClientServiceTests.cs b/IdentityShroud.Core.Tests/Services/ClientServiceTests.cs new file mode 100644 index 0000000..cb2e772 --- /dev/null +++ b/IdentityShroud.Core.Tests/Services/ClientServiceTests.cs @@ -0,0 +1,154 @@ +using IdentityShroud.Core.Contracts; +using IdentityShroud.Core.Model; +using IdentityShroud.Core.Services; +using IdentityShroud.Core.Tests.Fixtures; +using IdentityShroud.TestUtils.Substitutes; +using Microsoft.EntityFrameworkCore; + +namespace IdentityShroud.Core.Tests.Services; + +public class ClientServiceTests : IClassFixture +{ + private readonly DbFixture _dbFixture; + private readonly IEncryptionService _encryptionService = EncryptionServiceSubstitute.CreatePassthrough(); + private readonly IClock _clock = Substitute.For(); + private readonly Guid _realmId = new("a1b2c3d4-0000-0000-0000-000000000001"); + + public ClientServiceTests(DbFixture dbFixture) + { + _dbFixture = dbFixture; + using Db db = dbFixture.CreateDbContext(); + if (!db.Database.EnsureCreated()) + TruncateTables(db); + EnsureRealm(db); + } + + private void TruncateTables(Db db) + { + db.Database.ExecuteSqlRaw("TRUNCATE client CASCADE;"); + db.Database.ExecuteSqlRaw("TRUNCATE realm CASCADE;"); + } + + private void EnsureRealm(Db db) + { + if (!db.Realms.Any(r => r.Id == _realmId)) + { + db.Realms.Add(new() { Id = _realmId, Slug = "test-realm", Name = "Test Realm" }); + db.SaveChanges(); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task Create(bool allowClientCredentialsFlow) + { + // Setup + DateTime now = DateTime.UtcNow; + _clock.UtcNow().Returns(now); + + Client val; + await using (var db = _dbFixture.CreateDbContext()) + { + // Act + ClientService sut = new(db, _encryptionService, _clock); + var response = await sut.Create( + _realmId, + new ClientCreateRequest + { + ClientId = "test-client", + Name = "Test Client", + Description = "A test client", + AllowClientCredentialsFlow = allowClientCredentialsFlow, + }, + TestContext.Current.CancellationToken); + + // Verify + val = ResultAssert.Success(response); + Assert.Equal(_realmId, val.RealmId); + Assert.Equal("test-client", val.ClientId); + Assert.Equal("Test Client", val.Name); + Assert.Equal("A test client", val.Description); + Assert.Equal(allowClientCredentialsFlow, val.AllowClientCredentialsFlow); + Assert.Equal(now, val.CreatedAt); + } + + await using (var db = _dbFixture.CreateDbContext()) + { + var dbRecord = await db.Clients + .Include(e => e.Secrets) + .SingleAsync(e => e.Id == val.Id, TestContext.Current.CancellationToken); + + if (allowClientCredentialsFlow) + Assert.Single(dbRecord.Secrets); + else + Assert.Empty(dbRecord.Secrets); + } + } + + [Theory] + [InlineData("existing-client", true)] + [InlineData("missing-client", false)] + public async Task GetByClientId(string clientId, bool shouldFind) + { + // Setup + _clock.UtcNow().Returns(DateTime.UtcNow); + await using (var setupContext = _dbFixture.CreateDbContext()) + { + setupContext.Clients.Add(new() + { + RealmId = _realmId, + ClientId = "existing-client", + CreatedAt = DateTime.UtcNow, + }); + + await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken); + } + + await using var actContext = _dbFixture.CreateDbContext(); + // Act + ClientService sut = new(actContext, _encryptionService, _clock); + Client? result = await sut.GetByClientId(clientId, TestContext.Current.CancellationToken); + + // Verify + if (shouldFind) + Assert.NotNull(result); + else + Assert.Null(result); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task FindById(bool shouldFind) + { + // Setup + _clock.UtcNow().Returns(DateTime.UtcNow); + int existingId; + await using (var setupContext = _dbFixture.CreateDbContext()) + { + Client client = new() + { + RealmId = _realmId, + ClientId = "find-by-id-client", + CreatedAt = DateTime.UtcNow, + }; + setupContext.Clients.Add(client); + await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken); + existingId = client.Id; + } + + int searchId = shouldFind ? existingId : existingId + 9999; + + await using var actContext = _dbFixture.CreateDbContext(); + // Act + ClientService sut = new(actContext, _encryptionService, _clock); + Client? result = await sut.FindById(searchId, TestContext.Current.CancellationToken); + + // Verify + if (shouldFind) + Assert.NotNull(result); + else + Assert.Null(result); + } +} diff --git a/IdentityShroud.Core.Tests/Services/RealmServiceTests.cs b/IdentityShroud.Core.Tests/Services/RealmServiceTests.cs index d6aec76..60764bc 100644 --- a/IdentityShroud.Core.Tests/Services/RealmServiceTests.cs +++ b/IdentityShroud.Core.Tests/Services/RealmServiceTests.cs @@ -91,10 +91,47 @@ public class RealmServiceTests : IClassFixture } await using var actContext = _dbFixture.CreateDbContext(); - RealmService sut = new(actContext, _keyService); // Act + RealmService sut = new(actContext, _keyService); var result = await sut.FindBySlug(slug, TestContext.Current.CancellationToken); + // Verify Assert.Equal(name, result?.Name); } + + [Theory] + [InlineData("b0423bba-2411-497b-a5b6-c5adf404b862", true)] + [InlineData("65ac9dba-6d43-4fa4-b57f-133ed639fbcb", false)] + public async Task FindById(string idString, bool shouldFind) + { + Guid id = new(idString); + await using (var setupContext = _dbFixture.CreateDbContext()) + { + setupContext.Realms.Add(new() + { + Id = new("b0423bba-2411-497b-a5b6-c5adf404b862"), + Slug = "foo", + Name = "Foo", + }); + setupContext.Realms.Add(new() + { + Id = new("d4ffc7d0-7b2c-4f02-82b9-a74610435b0d"), + Slug = "bar", + Name = "Bar", + }); + + await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken); + } + + await using var actContext = _dbFixture.CreateDbContext(); + // Act + RealmService sut = new(actContext, _keyService); + Realm? result = await sut.FindById(id, TestContext.Current.CancellationToken); + + // Verify + if (shouldFind) + Assert.NotNull(result); + else + Assert.Null(result); + } } \ No newline at end of file diff --git a/IdentityShroud.sln.DotSettings.user b/IdentityShroud.sln.DotSettings.user index 9992676..e39022f 100644 --- a/IdentityShroud.sln.DotSettings.user +++ b/IdentityShroud.sln.DotSettings.user @@ -22,9 +22,12 @@ /home/eelke/.cache/JetBrains/Rider2025.3/resharper-host/temp/Rider/vAny/CoverageData/_IdentityShroud.-1277985570/Snapshot/snapshot.utdcvr /home/eelke/.dotnet/dotnet /home/eelke/.dotnet/sdk/10.0.102/MSBuild.dll - <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <SessionState ContinuousTestingMode="0" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> <Solution /> </SessionState> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="Junie Session" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <ProjectFile>DC887623-8680-4D3B-B23A-D54F7DA91891/d:Services/f:ClientServiceTests.cs</ProjectFile> +</SessionState>