From 1c8144f129e369f3b8d8d8d86773b292c0ffb109 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 11:53:53 +0300 Subject: [PATCH 01/25] initial commit --- unreleased.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unreleased.md b/unreleased.md index f514bbb89..930dc74f0 100644 --- a/unreleased.md +++ b/unreleased.md @@ -1,3 +1,3 @@ # Unreleased - +initial commit From abe94eda27d64a6286d91e248954f10e6fb3b3ed Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:28:48 +0300 Subject: [PATCH 02/25] add some test cases & helpers --- .../TestServiceSpec.cs | 9 +++++ .../TestServiceSpecExtensions.cs | 28 ++++++++++++++ .../Transaction.cs | 37 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs index 2b0bad3ea..06cc4e0d7 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs @@ -13,4 +13,13 @@ static TestServiceSpec() => protected override string? GetDefaultSettingsValue(string key) => key == "Int" ? "42" : "test value"; + + public void VerifyPersists(Entity entity) + { + var entities = GiveMe.The(); + + var result = entities.By(entity.String).FirstOrDefault(e => e.Guid == entity.Guid); + + result.ShouldNotBeNull(); + } } \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs new file mode 100644 index 000000000..8a3ea20a8 --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -0,0 +1,28 @@ +using Do.Testing; + +namespace Do.Test; + +public static class TestServiceSpecExtensions +{ + public static Entity AnEntity(this Stubber giveMe, + Guid? guid = default, + string? @string = default, + string? stringData = default, + int? int32 = default, + Uri? uri = default, + object? @dynamic = default, + Status? status = default + ) + { + return giveMe. + A(). + With( + guid ?? Guid.NewGuid(), + @string ?? string.Empty, + stringData ?? string.Empty, + int32 ?? 0, uri ?? giveMe.AUrl(), + dynamic ?? new { }, + status ?? Status.Disabled + ); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs new file mode 100644 index 000000000..3185bdcef --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -0,0 +1,37 @@ +namespace Do.Test; + +public class Transaction : TestServiceSpec +{ + [Test] + public void Created_entity_persists() + { + var entity = GiveMe.AnEntity(); + + VerifyPersists(entity); + } + + [Test] + public async Task Entity_update_does_not_rollback_when_done_asynchronously_if_an_error_occurs() + { + var entity = GiveMe.AnEntity(@string: "test"); + var entities = GiveMe.The(); + var task = entity.Update( + guid: entity.Guid, + @string: "updated", + stringData: entity.StringData, + int32: entity.Int32, + uri: entity.Uri, + dynamic: entity.Dynamic, + status: entity.Status, + useTransaction: true, + throwError: true + ); + + await task.ShouldThrowAsync(); + + var result = entities.By("updated").FirstOrDefault(e => e.Guid == entity.Guid); + + result.ShouldNotBeNull(); + result.String.ShouldBe(entity.String); + } +} From 02fa833209fee8046bf7afad3d3efd7263c57ef5 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:37:12 +0300 Subject: [PATCH 03/25] include test project in code coverage report --- test/runsettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runsettings.xml b/test/runsettings.xml index 3c450b593..e83fd926c 100644 --- a/test/runsettings.xml +++ b/test/runsettings.xml @@ -5,7 +5,7 @@ cobertura - [Do.Blueprints.*]*,[Do.Test.Blueprints.*]* + [Do.Blueprints.*]* false false From 7f883ab09087646bfc115f7bbed8bfbb0c9f9145 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:41:03 +0300 Subject: [PATCH 04/25] remove service application from coverage report --- test/runsettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runsettings.xml b/test/runsettings.xml index e83fd926c..d11aa14a8 100644 --- a/test/runsettings.xml +++ b/test/runsettings.xml @@ -5,7 +5,7 @@ cobertura - [Do.Blueprints.*]* + [Do.Blueprints.*]*,[Do.Test.Blueprints.]* false false From 5833abc4ae09f8a61badf01b47a9fd1882e219c2 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:43:42 +0300 Subject: [PATCH 05/25] fix wildcard --- test/runsettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runsettings.xml b/test/runsettings.xml index d11aa14a8..3c450b593 100644 --- a/test/runsettings.xml +++ b/test/runsettings.xml @@ -5,7 +5,7 @@ cobertura - [Do.Blueprints.*]*,[Do.Test.Blueprints.]* + [Do.Blueprints.*]*,[Do.Test.Blueprints.*]* false false From 516be16c1666a9a4bb39348badbf81e5a6764b5e Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:50:32 +0300 Subject: [PATCH 06/25] fix exclude --- test/runsettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runsettings.xml b/test/runsettings.xml index 3c450b593..609f420f1 100644 --- a/test/runsettings.xml +++ b/test/runsettings.xml @@ -5,7 +5,7 @@ cobertura - [Do.Blueprints.*]*,[Do.Test.Blueprints.*]* + [Do.Blueprints.*]*,[Do.Test.Blueprints.Service.*]* false false From 168f8f9e6328aa69d1be99eadd8ba0ac9983c6dd Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 14:59:30 +0300 Subject: [PATCH 07/25] add entity delete case --- .../Do.Test.Blueprints.Service.Test/Transaction.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs index 3185bdcef..67b456163 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -34,4 +34,17 @@ public async Task Entity_update_does_not_rollback_when_done_asynchronously_if_an result.ShouldNotBeNull(); result.String.ShouldBe(entity.String); } + + [Test] + public void Entity_does_not_persist_when_deleted() + { + var entity = GiveMe.AnEntity(); + var entities = GiveMe.The(); + + VerifyPersists(entity); + + entity.Delete(); + + entities.By(@string: entity.String).FirstOrDefault(e => e.Guid == entity.Guid).ShouldBeNull(); + } } From 0b49fdd0f9715fec38de1e3afd48f0309384af39 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 15:52:31 +0300 Subject: [PATCH 08/25] use existing helpers for persist and delete assertions --- .../Do.Test.Blueprints.Service.Test/TestServiceSpec.cs | 9 --------- .../Do.Test.Blueprints.Service.Test/Transaction.cs | 7 +++---- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs index 06cc4e0d7..2b0bad3ea 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpec.cs @@ -13,13 +13,4 @@ static TestServiceSpec() => protected override string? GetDefaultSettingsValue(string key) => key == "Int" ? "42" : "test value"; - - public void VerifyPersists(Entity entity) - { - var entities = GiveMe.The(); - - var result = entities.By(entity.String).FirstOrDefault(e => e.Guid == entity.Guid); - - result.ShouldNotBeNull(); - } } \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs index 67b456163..37d20ac92 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -7,7 +7,7 @@ public void Created_entity_persists() { var entity = GiveMe.AnEntity(); - VerifyPersists(entity); + entity.ShouldBeInserted(); } [Test] @@ -39,12 +39,11 @@ public async Task Entity_update_does_not_rollback_when_done_asynchronously_if_an public void Entity_does_not_persist_when_deleted() { var entity = GiveMe.AnEntity(); - var entities = GiveMe.The(); - VerifyPersists(entity); + entity.ShouldBeInserted(); entity.Delete(); - entities.By(@string: entity.String).FirstOrDefault(e => e.Guid == entity.Guid).ShouldBeNull(); + entity.ShouldBeDeleted(); } } From 5b1030340271bd62e97a73231f088b025c5a4238 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 16:08:26 +0300 Subject: [PATCH 09/25] Test singleton and transient lifecycle --- .../Transaction.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs index 37d20ac92..528af5bd5 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -46,4 +46,22 @@ public void Entity_does_not_persist_when_deleted() entity.ShouldBeDeleted(); } + + [Test] + public void A_single_instance_of_singleton_is_shared_across_application() + { + var singleton1 = GiveMe.The(); + var singleton2 = GiveMe.The(); + + singleton1.ShouldBe(singleton2); + } + + [Test] + public void New_instance_of_transient_is_created_at_each_request() + { + var entity1 = GiveMe.An(); + var entity2 = GiveMe.An(); + + entity1.ShouldNotBe(entity2); + } } From 16df5959cc34367b5099d7f13c0bb2c2e4220adc Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 16:34:37 +0300 Subject: [PATCH 10/25] add special characters in object property corrupts data, case --- .../Do.Test.Blueprints.Service.Test/Transaction.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs index 528af5bd5..57efbb2a5 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -64,4 +64,17 @@ public void New_instance_of_transient_is_created_at_each_request() entity1.ShouldNotBe(entity2); } + + [Test] + public void Special_characters_do_not_cause_corrupted_data_for_object_properties() + { + var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); + var entities = GiveMe.The(); + + entity.ShouldBeInserted(); + + Func> task = () => entities.By(entity.String); + + task.ShouldNotThrow(); + } } From 5d2347f2f1f90bad31848f432b1832325584d35b Mon Sep 17 00:00:00 2001 From: alptuncs Date: Fri, 24 Nov 2023 17:19:02 +0300 Subject: [PATCH 11/25] add singleton entity tests, !Tests Failing! --- .../Transaction.cs | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs index 57efbb2a5..91298555b 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs @@ -1,4 +1,6 @@ -namespace Do.Test; +using Do.ExceptionHandling; + +namespace Do.Test; public class Transaction : TestServiceSpec { @@ -29,10 +31,10 @@ public async Task Entity_update_does_not_rollback_when_done_asynchronously_if_an await task.ShouldThrowAsync(); - var result = entities.By("updated").FirstOrDefault(e => e.Guid == entity.Guid); + var result = entities.By().FirstOrDefault(e => e.Guid == entity.Guid); result.ShouldNotBeNull(); - result.String.ShouldBe(entity.String); + result.String.ShouldBe("updated"); } [Test] @@ -77,4 +79,52 @@ public void Special_characters_do_not_cause_corrupted_data_for_object_properties task.ShouldNotThrow(); } + + [Test] + public void TestException_throws_handled_exception_when_the_handled_bool_flag_is_provided() + { + var singleton = GiveMe.The(); + + Action task = () => singleton.TestException(handled: true); + + task.ShouldThrow(); + } + + [Test] + public void TestException_throws_unhandled_exception_when_the_handled_bool_flag_is_provided() + { + var singleton = GiveMe.The(); + + Action task = () => singleton.TestException(handled: false); + + task.ShouldThrow(); + } + + [Test] + public async Task Transaction_committed_asynchronously_does_not_rollback_when_error_occurs() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); + + var task = singleton.TestTransactionAction(); + + await task.ShouldThrowAsync(); + entities.By().ShouldNotBeEmpty(); + } + + [Test] + public async Task Synchronous_update_is_not_committed_when_an_error_occurs_during_transaction() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); + + var task = singleton.TestTransactionFunc(); + + await task.ShouldThrowAsync(); + + var entity = entities.By().FirstOrDefault(); + + entity.ShouldNotBeNull(); + entity.String.ShouldNotBeSameAs("rollback"); + } } From 20b4217362a5459bca1a45d3c406fff4816cd66c Mon Sep 17 00:00:00 2001 From: alptuncs Date: Tue, 28 Nov 2023 12:14:32 +0300 Subject: [PATCH 12/25] remove rollback case, move tests to relevant fixtures --- .../NHibernateUserType/CorruptedData.cs | 17 +++ .../DataAccess/PersistingEntity.cs | 61 ++++++++ .../DependencyInjection/ServiceLifetime.cs | 22 +++ .../Transaction.cs | 130 ------------------ 4 files changed, 100 insertions(+), 130 deletions(-) create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs delete mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs new file mode 100644 index 000000000..e246190bf --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs @@ -0,0 +1,17 @@ +namespace Do.Test.DataAccess.NHibernateUserType; + +public class CorruptedData : TestServiceSpec +{ + [Test] + public void Special_characters_do_not_cause_corrupted_data_for_object_user_type_properties() + { + var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); + var entities = GiveMe.The(); + + entity.ShouldBeInserted(); + + Func> task = () => entities.By(entity.String); + + task.ShouldNotThrow(); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs new file mode 100644 index 000000000..e2042c3f2 --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -0,0 +1,61 @@ +namespace Do.Test.DataAccess; + +public class PersistingEntity : TestServiceSpec +{ + [Test] + public void Created_entity_persists() + { + var entity = GiveMe.AnEntity(); + + entity.ShouldBeInserted(); + } + + [Test] + public void Entity_does_not_persist_when_deleted() + { + var entity = GiveMe.AnEntity(); + + entity.ShouldBeInserted(); + + entity.Delete(); + + entity.ShouldBeDeleted(); + } + + [Test] + public async Task Entity_update_commits_when_done_asynchronously_if_an_error_occurs() + { + var entity = GiveMe.AnEntity(@string: "test"); + var entities = GiveMe.The(); + var task = entity.Update( + guid: entity.Guid, + @string: "updated", + stringData: entity.StringData, + int32: entity.Int32, + uri: entity.Uri, + dynamic: entity.Dynamic, + status: entity.Status, + useTransaction: true, + throwError: true + ); + + await task.ShouldThrowAsync(); + + var result = entities.By().FirstOrDefault(e => e.Guid == entity.Guid); + + result.ShouldNotBeNull(); + result.String.ShouldBe("updated"); + } + + [Test] + public async Task Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); + + var task = singleton.TestTransactionAction(); + + await task.ShouldThrowAsync(); + entities.By().ShouldNotBeEmpty(); + } +} \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs new file mode 100644 index 000000000..36f00f18e --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs @@ -0,0 +1,22 @@ +namespace Do.Test.DependencyInjection; + +public class ServiceLifetime : TestServiceSpec +{ + [Test] + public void A_single_instance_of_singleton_is_shared_across_application() + { + var singleton1 = GiveMe.The(); + var singleton2 = GiveMe.The(); + + singleton1.ShouldBe(singleton2); + } + + [Test] + public void New_instance_of_transient_is_created_at_each_request() + { + var entity1 = GiveMe.An(); + var entity2 = GiveMe.An(); + + entity1.ShouldNotBe(entity2); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs deleted file mode 100644 index 91298555b..000000000 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Transaction.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Do.ExceptionHandling; - -namespace Do.Test; - -public class Transaction : TestServiceSpec -{ - [Test] - public void Created_entity_persists() - { - var entity = GiveMe.AnEntity(); - - entity.ShouldBeInserted(); - } - - [Test] - public async Task Entity_update_does_not_rollback_when_done_asynchronously_if_an_error_occurs() - { - var entity = GiveMe.AnEntity(@string: "test"); - var entities = GiveMe.The(); - var task = entity.Update( - guid: entity.Guid, - @string: "updated", - stringData: entity.StringData, - int32: entity.Int32, - uri: entity.Uri, - dynamic: entity.Dynamic, - status: entity.Status, - useTransaction: true, - throwError: true - ); - - await task.ShouldThrowAsync(); - - var result = entities.By().FirstOrDefault(e => e.Guid == entity.Guid); - - result.ShouldNotBeNull(); - result.String.ShouldBe("updated"); - } - - [Test] - public void Entity_does_not_persist_when_deleted() - { - var entity = GiveMe.AnEntity(); - - entity.ShouldBeInserted(); - - entity.Delete(); - - entity.ShouldBeDeleted(); - } - - [Test] - public void A_single_instance_of_singleton_is_shared_across_application() - { - var singleton1 = GiveMe.The(); - var singleton2 = GiveMe.The(); - - singleton1.ShouldBe(singleton2); - } - - [Test] - public void New_instance_of_transient_is_created_at_each_request() - { - var entity1 = GiveMe.An(); - var entity2 = GiveMe.An(); - - entity1.ShouldNotBe(entity2); - } - - [Test] - public void Special_characters_do_not_cause_corrupted_data_for_object_properties() - { - var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); - var entities = GiveMe.The(); - - entity.ShouldBeInserted(); - - Func> task = () => entities.By(entity.String); - - task.ShouldNotThrow(); - } - - [Test] - public void TestException_throws_handled_exception_when_the_handled_bool_flag_is_provided() - { - var singleton = GiveMe.The(); - - Action task = () => singleton.TestException(handled: true); - - task.ShouldThrow(); - } - - [Test] - public void TestException_throws_unhandled_exception_when_the_handled_bool_flag_is_provided() - { - var singleton = GiveMe.The(); - - Action task = () => singleton.TestException(handled: false); - - task.ShouldThrow(); - } - - [Test] - public async Task Transaction_committed_asynchronously_does_not_rollback_when_error_occurs() - { - var singleton = GiveMe.The(); - var entities = GiveMe.The(); - - var task = singleton.TestTransactionAction(); - - await task.ShouldThrowAsync(); - entities.By().ShouldNotBeEmpty(); - } - - [Test] - public async Task Synchronous_update_is_not_committed_when_an_error_occurs_during_transaction() - { - var singleton = GiveMe.The(); - var entities = GiveMe.The(); - - var task = singleton.TestTransactionFunc(); - - await task.ShouldThrowAsync(); - - var entity = entities.By().FirstOrDefault(); - - entity.ShouldNotBeNull(); - entity.String.ShouldNotBeSameAs("rollback"); - } -} From 88d49a2746322f35f37dc48a1b88b5a9d0e2a343 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Tue, 28 Nov 2023 17:42:21 +0300 Subject: [PATCH 13/25] Commit Async should take nullable parameter --- .../Database/FlatTransaction.cs | 8 ++++++-- .../Database/InMemory/SkippedTransaction.cs | 8 ++++++-- .../Do.Blueprints.Service/Database/ITransaction.cs | 4 ++-- .../RestApi/Analyzer/Singleton.generated.cs | 10 ++++++++++ .../DataAccess/Transaction/CommitAsync.cs | 13 +++++++++++++ .../Do.Test.Blueprints.Service/Singleton.cs | 7 +++++++ 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs diff --git a/src/blueprints/Do.Blueprints.Service.Application/Database/FlatTransaction.cs b/src/blueprints/Do.Blueprints.Service.Application/Database/FlatTransaction.cs index 800da741d..0d86dc069 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/Database/FlatTransaction.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/Database/FlatTransaction.cs @@ -43,15 +43,19 @@ public async Task CommitAsync(Func> action) return result; } - public async Task CommitAsync(TEntity entity, Action action) + public async Task CommitAsync(TEntity? entity, Action action) { + if (entity is null) { return; } + action(entity); await CommitAndBeginNewTransaction(); } - public async Task CommitAsync(TEntity entity, Func action) + public async Task CommitAsync(TEntity? entity, Func action) { + if (entity is null) { return; } + await action(entity); await CommitAndBeginNewTransaction(); diff --git a/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs b/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs index 29e0bb6d0..09efe71b4 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs @@ -26,15 +26,19 @@ public async Task CommitAsync(Func> action) return await action(); } - public Task CommitAsync(TEntity entity, Action action) + public Task CommitAsync(TEntity? entity, Action action) { + if (entity is null) { return new(() => { }); } + action(entity); return Task.CompletedTask; } - public async Task CommitAsync(TEntity entity, Func action) + public async Task CommitAsync(TEntity? entity, Func action) { + if (entity is null) { return; } + await action(entity); } } diff --git a/src/blueprints/Do.Blueprints.Service/Database/ITransaction.cs b/src/blueprints/Do.Blueprints.Service/Database/ITransaction.cs index ed7d3d752..79eecf4ba 100644 --- a/src/blueprints/Do.Blueprints.Service/Database/ITransaction.cs +++ b/src/blueprints/Do.Blueprints.Service/Database/ITransaction.cs @@ -8,6 +8,6 @@ public interface ITransaction Task CommitAsync(Func action); Task CommitAsync(Func> action); - Task CommitAsync(TEntity entity, Action action); - Task CommitAsync(TEntity entity, Func action); + Task CommitAsync(TEntity? entity, Action action); + Task CommitAsync(TEntity? entity, Func action); } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs index 1c0a4a879..45ce5a7fe 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs @@ -54,6 +54,16 @@ public void TestException(bool handled) target.TestException(handled); } + [HttpPost] + [Produces("application/json")] + [Route("singleton/test-transaction-nullable")] + public async Task TestTransactionNullable() + { + var target = _serviceProvider.GetRequiredService(); + + await target.TestTransactionNullable(null); + } + [HttpPut] [Produces("application/json")] [Route("singleton/test-async-object")] diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs new file mode 100644 index 000000000..1346aebb8 --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs @@ -0,0 +1,13 @@ +namespace Do.Test.DataAccess.Transaction; + +public class CommitAsync : TestServiceSpec +{ + [Test] + public async Task Commit_async_takes_nullable_parameters() + { + var singleton = GiveMe.The(); + var task = singleton.TestTransactionNullable(null); + + await task.ShouldNotThrowAsync(); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs index d876c63a0..ccb1e97a3 100644 --- a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs +++ b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs @@ -59,4 +59,11 @@ public async Task TestAsyncObject(object request) return request; } + + public async Task TestTransactionNullable(Entity? entity) + { + await _transaction.CommitAsync(entity, entity => + entity.Update(Guid.NewGuid(), "test", "transaction func", 1, new("https://func.com"), new { transaction = "func" }, Status.Enabled) + ); + } } From 83cc8eab86485ff028050e2821d9e6c28582afbb Mon Sep 17 00:00:00 2001 From: alptuncs Date: Tue, 28 Nov 2023 19:00:43 +0300 Subject: [PATCH 14/25] Make ASetting generic --- .../ServiceSpecExtensions.cs | 7 +++---- .../Configuration/MockingConfiguration.cs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs index cf6042418..af3f8b0ab 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs @@ -126,17 +126,16 @@ public static void ShouldHaveOneParameter(this MethodInfo source) #region Settings - public static void ASetting(this Mocker mockMe, + public static void ASetting(this Mocker mockMe, string? key = default, - string? value = default + T? value = default ) { key ??= "Test:Configuration"; - value ??= "value"; var spec = (ServiceSpec)mockMe.Spec; - spec.Settings[key] = value; + spec.Settings[key] = value is null ? "value" : $"{value}"; } internal static IConfiguration TheConfiguration(this Mocker mockMe, diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs index 87ec72ef9..cc5514de3 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs @@ -15,6 +15,20 @@ public void Mock_configuration_returns_mocked_settings_value() actual.ShouldBe(10); } + [TestCase(42)] + [TestCase("value")] + [TestCase(false)] + [Test] + public void Mock_ASetting_value_parameter_is_generic(T value) + { + MockMe.ASetting("Config", value); + var configuration = GiveMe.The(); + + var actual = configuration.GetRequiredValue("Config"); + + actual.ShouldBeEquivalentTo(value); + } + [TestCase("Int", 42)] // defined in TestServiceSpec [TestCase("String", "test value")] // defined in TestServiceSpec public void Mock_configuration_uses_settings_value_provider_for_not_mocked_config_sections(string key, object value) From 48d207ec1f38ebdbeb3475613b7f00e3316196c5 Mon Sep 17 00:00:00 2001 From: Sefer Mirza Date: Wed, 29 Nov 2023 12:47:38 +0300 Subject: [PATCH 15/25] review changes --- .../Database/InMemory/SkippedTransaction.cs | 2 +- .../ServiceSpecExtensions.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs b/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs index 09efe71b4..c6547f90b 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/Database/InMemory/SkippedTransaction.cs @@ -28,7 +28,7 @@ public async Task CommitAsync(Func> action) public Task CommitAsync(TEntity? entity, Action action) { - if (entity is null) { return new(() => { }); } + if (entity is null) { return Task.CompletedTask; } action(entity); diff --git a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs index af3f8b0ab..8bee693af 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs @@ -126,6 +126,11 @@ public static void ShouldHaveOneParameter(this MethodInfo source) #region Settings + public static void ASetting(this Mocker mockMe, + string? key = default, + string? value = default + ) => mockMe.ASetting(key: key ?? "Test:Configuration", value: value ?? "value"); + public static void ASetting(this Mocker mockMe, string? key = default, T? value = default From 85a04248e26b49e8feef7d081ffb253bb30bd70f Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 12:49:39 +0300 Subject: [PATCH 16/25] review --- .../DataAccess/PersistingEntity.cs | 2 -- .../DependencyInjection/ServiceLifetime.cs | 4 ++-- .../TestServiceSpecExtensions.cs | 20 +++++++++---------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs index e2042c3f2..4cdec3d7c 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -15,8 +15,6 @@ public void Entity_does_not_persist_when_deleted() { var entity = GiveMe.AnEntity(); - entity.ShouldBeInserted(); - entity.Delete(); entity.ShouldBeDeleted(); diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs index 36f00f18e..5191fc1b4 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/ServiceLifetime.cs @@ -8,7 +8,7 @@ public void A_single_instance_of_singleton_is_shared_across_application() var singleton1 = GiveMe.The(); var singleton2 = GiveMe.The(); - singleton1.ShouldBe(singleton2); + singleton1.ShouldBeSameAs(singleton2); } [Test] @@ -17,6 +17,6 @@ public void New_instance_of_transient_is_created_at_each_request() var entity1 = GiveMe.An(); var entity2 = GiveMe.An(); - entity1.ShouldNotBe(entity2); + entity1.ShouldNotBeSameAs(entity2); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 8a3ea20a8..284bf1dc1 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -14,15 +14,15 @@ public static Entity AnEntity(this Stubber giveMe, Status? status = default ) { - return giveMe. - A(). - With( - guid ?? Guid.NewGuid(), - @string ?? string.Empty, - stringData ?? string.Empty, - int32 ?? 0, uri ?? giveMe.AUrl(), - dynamic ?? new { }, - status ?? Status.Disabled - ); + return giveMe + .A() + .With( + guid ?? Guid.NewGuid(), + @string ?? string.Empty, + stringData ?? string.Empty, + int32 ?? 0, uri ?? giveMe.AUrl(), + dynamic ?? new { }, + status ?? Status.Disabled + ); } } From 085bfa43ba49e3a2dd19359ae6c0e76b324503fe Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 13:57:53 +0300 Subject: [PATCH 17/25] review --- .../ServiceSpecExtensions.cs | 4 ++-- .../RestApi/Analyzer/Singleton.generated.cs | 4 ++-- .../DataAccess/PersistingEntity.cs | 8 ++++---- .../DataAccess/Transaction/CommitAsync.cs | 20 +++++++++++++++++-- .../TestServiceSpecExtensions.cs | 18 ++++++++--------- unreleased.md | 5 ++++- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs index 8bee693af..3ed01ce17 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs @@ -129,7 +129,7 @@ public static void ShouldHaveOneParameter(this MethodInfo source) public static void ASetting(this Mocker mockMe, string? key = default, string? value = default - ) => mockMe.ASetting(key: key ?? "Test:Configuration", value: value ?? "value"); + ) => mockMe.ASetting(key: key ?? "Test:Configuration", value: value ?? "value"); public static void ASetting(this Mocker mockMe, string? key = default, @@ -140,7 +140,7 @@ public static void ASetting(this Mocker mockMe, var spec = (ServiceSpec)mockMe.Spec; - spec.Settings[key] = value is null ? "value" : $"{value}"; + spec.Settings[key] = $"{value}"; } internal static IConfiguration TheConfiguration(this Mocker mockMe, diff --git a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs index 45ce5a7fe..2511a0877 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs @@ -57,11 +57,11 @@ public void TestException(bool handled) [HttpPost] [Produces("application/json")] [Route("singleton/test-transaction-nullable")] - public async Task TestTransactionNullable() + public async Task TestTransactionNullable([FromBody] Entity entity = default) { var target = _serviceProvider.GetRequiredService(); - await target.TestTransactionNullable(null); + await target.TestTransactionNullable(entity); } [HttpPut] diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs index 4cdec3d7c..a31e4c798 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -21,7 +21,7 @@ public void Entity_does_not_persist_when_deleted() } [Test] - public async Task Entity_update_commits_when_done_asynchronously_if_an_error_occurs() + public void Entity_update_commits_when_done_asynchronously_if_an_error_occurs() { var entity = GiveMe.AnEntity(@string: "test"); var entities = GiveMe.The(); @@ -37,7 +37,7 @@ public async Task Entity_update_commits_when_done_asynchronously_if_an_error_occ throwError: true ); - await task.ShouldThrowAsync(); + task.ShouldThrow(); var result = entities.By().FirstOrDefault(e => e.Guid == entity.Guid); @@ -46,14 +46,14 @@ public async Task Entity_update_commits_when_done_asynchronously_if_an_error_occ } [Test] - public async Task Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() + public void Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() { var singleton = GiveMe.The(); var entities = GiveMe.The(); var task = singleton.TestTransactionAction(); - await task.ShouldThrowAsync(); + task.ShouldThrow(); entities.By().ShouldNotBeEmpty(); } } \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs index 1346aebb8..9228a1c2e 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs @@ -3,11 +3,27 @@ public class CommitAsync : TestServiceSpec { [Test] - public async Task Commit_async_takes_nullable_parameters() + public void Commit_async_takes_nullable_parameters() { var singleton = GiveMe.The(); var task = singleton.TestTransactionNullable(null); - await task.ShouldNotThrowAsync(); + task.ShouldNotThrow(); + } + + [Test] + public void Commit_async_update_occurs_when_entity_is_not_null() + { + var entity = GiveMe.AnEntity(@string: "string"); + var entitites = GiveMe.The(); + var singleton = GiveMe.The(); + var task = singleton.TestTransactionNullable(entity); + + task.ShouldNotThrow(); + + var actual = entitites.By().FirstOrDefault(); + + actual.ShouldNotBeNull(); + actual.String.ShouldNotBe("string"); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 284bf1dc1..7444768ee 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -15,14 +15,14 @@ public static Entity AnEntity(this Stubber giveMe, ) { return giveMe - .A() - .With( - guid ?? Guid.NewGuid(), - @string ?? string.Empty, - stringData ?? string.Empty, - int32 ?? 0, uri ?? giveMe.AUrl(), - dynamic ?? new { }, - status ?? Status.Disabled - ); + .A() + .With( + guid ?? Guid.NewGuid(), + @string ?? string.Empty, + stringData ?? string.Empty, + int32 ?? 0, uri ?? giveMe.AUrl(), + dynamic ?? new { }, + status ?? Status.Disabled + ); } } diff --git a/unreleased.md b/unreleased.md index 930dc74f0..ea7442414 100644 --- a/unreleased.md +++ b/unreleased.md @@ -1,3 +1,6 @@ # Unreleased -initial commit +### Improvements + +- `CommitAsync` now accepts nullable parameters. +- Added generic overload for `MockMe.ASetting()`. From 726341934156c6b7064e90d9b11574b169d7c778 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 14:07:21 +0300 Subject: [PATCH 18/25] review --- .../Configuration/MockingConfiguration.cs | 1 - .../DataAccess/NHibernateUserType/CorruptedData.cs | 2 -- .../DataAccess/PersistingEntity.cs | 14 ++++++++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs index cc5514de3..5fdf25881 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs @@ -18,7 +18,6 @@ public void Mock_configuration_returns_mocked_settings_value() [TestCase(42)] [TestCase("value")] [TestCase(false)] - [Test] public void Mock_ASetting_value_parameter_is_generic(T value) { MockMe.ASetting("Config", value); diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs index e246190bf..5f2a39a72 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs @@ -8,8 +8,6 @@ public void Special_characters_do_not_cause_corrupted_data_for_object_user_type_ var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); var entities = GiveMe.The(); - entity.ShouldBeInserted(); - Func> task = () => entities.By(entity.String); task.ShouldNotThrow(); diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs index a31e4c798..5c39e7645 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -5,9 +5,19 @@ public class PersistingEntity : TestServiceSpec [Test] public void Created_entity_persists() { - var entity = GiveMe.AnEntity(); + var newEntity = GiveMe.A>(); + + var actual = newEntity().With( + guid: Guid.NewGuid(), + @string: string.Empty, + stringData: string.Empty, + int32: 0, + uri: GiveMe.AUrl(), + @dynamic: new { }, + status: Status.Disabled + ); - entity.ShouldBeInserted(); + actual.ShouldBeInserted(); } [Test] From c1fabce98eddf3819e59d9267ca2e7897acb22e3 Mon Sep 17 00:00:00 2001 From: Sefer Mirza Date: Wed, 29 Nov 2023 14:52:59 +0300 Subject: [PATCH 19/25] review --- .../NHibernateUserType/CorruptedData.cs | 15 ------- .../DataAccess/PersistingEntity.cs | 36 +++------------- .../DataAccess/Transaction/CommitAsync.cs | 17 ++++++-- .../Do.Test.Blueprints.Service/Singleton.cs | 42 ++++++++++++++++--- 4 files changed, 55 insertions(+), 55 deletions(-) delete mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs deleted file mode 100644 index 5f2a39a72..000000000 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/NHibernateUserType/CorruptedData.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Do.Test.DataAccess.NHibernateUserType; - -public class CorruptedData : TestServiceSpec -{ - [Test] - public void Special_characters_do_not_cause_corrupted_data_for_object_user_type_properties() - { - var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); - var entities = GiveMe.The(); - - Func> task = () => entities.By(entity.String); - - task.ShouldNotThrow(); - } -} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs index 5c39e7645..e7f7cb75c 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -21,7 +21,7 @@ public void Created_entity_persists() } [Test] - public void Entity_does_not_persist_when_deleted() + public void Entity_is_deleted_successfully() { var entity = GiveMe.AnEntity(); @@ -31,39 +31,13 @@ public void Entity_does_not_persist_when_deleted() } [Test] - public void Entity_update_commits_when_done_asynchronously_if_an_error_occurs() + public void Object_user_type_supports_special_characters_to_be_used_within_strings() { - var entity = GiveMe.AnEntity(@string: "test"); - var entities = GiveMe.The(); - var task = entity.Update( - guid: entity.Guid, - @string: "updated", - stringData: entity.StringData, - int32: entity.Int32, - uri: entity.Uri, - dynamic: entity.Dynamic, - status: entity.Status, - useTransaction: true, - throwError: true - ); - - task.ShouldThrow(); - - var result = entities.By().FirstOrDefault(e => e.Guid == entity.Guid); - - result.ShouldNotBeNull(); - result.String.ShouldBe("updated"); - } - - [Test] - public void Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() - { - var singleton = GiveMe.The(); + var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); var entities = GiveMe.The(); - var task = singleton.TestTransactionAction(); + Func> task = () => entities.By(entity.String); - task.ShouldThrow(); - entities.By().ShouldNotBeEmpty(); + task.ShouldNotThrow(); } } \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs index 9228a1c2e..a66a762b8 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs @@ -6,6 +6,7 @@ public class CommitAsync : TestServiceSpec public void Commit_async_takes_nullable_parameters() { var singleton = GiveMe.The(); + var task = singleton.TestTransactionNullable(null); task.ShouldNotThrow(); @@ -15,15 +16,23 @@ public void Commit_async_takes_nullable_parameters() public void Commit_async_update_occurs_when_entity_is_not_null() { var entity = GiveMe.AnEntity(@string: "string"); - var entitites = GiveMe.The(); var singleton = GiveMe.The(); + var task = singleton.TestTransactionNullable(entity); task.ShouldNotThrow(); + entity.String.ShouldNotBe("string"); + } + + [Test] + public void Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); - var actual = entitites.By().FirstOrDefault(); + var task = singleton.TestTransactionAction(); - actual.ShouldNotBeNull(); - actual.String.ShouldNotBe("string"); + task.ShouldThrow(); + entities.By().ShouldNotBeEmpty(); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs index ccb1e97a3..8b9e4944a 100644 --- a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs +++ b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs @@ -34,7 +34,15 @@ public async Task TestTransactionAction() await _transaction.CommitAsync(() => { // do not remove this variable, this is to ensure call is made to `Action` overload - var _ = _newEntity().With(Guid.NewGuid(), "test", "transaction action", 1, new("https://action.com"), new { transaction = "action" }, Status.Enabled); + var _ = _newEntity().With( + guid: Guid.NewGuid(), + @string: "test", + stringData: "transaction action", + int32: 1, + uri: new("https://action.com"), + @dynamic: new { transaction = "action" }, + status: Status.Enabled + ); }); throw new(); @@ -43,10 +51,26 @@ await _transaction.CommitAsync(() => public async Task TestTransactionFunc() { var entity = await _transaction.CommitAsync(() => - _newEntity().With(Guid.NewGuid(), "test", "transaction func", 1, new("https://func.com"), new { transaction = "func" }, Status.Enabled) + _newEntity().With( + guid: Guid.NewGuid(), + @string: "test", + stringData: "transaction func", + int32: 1, + uri: new("https://func.com"), + @dynamic: new { transaction = "func" }, + status: Status.Enabled + ) ); - await entity.Update(Guid.NewGuid(), "rollback", "rollback", 2, new("https://rollback.com"), new { rollback = "rollback" }, Status.Disabled); + await entity.Update( + guid: Guid.NewGuid(), + @string: "rollback", + stringData: "rollback", + int32: 2, + uri: new("https://rollback.com"), + @dynamic: new { rollback = "rollback" }, + status: Status.Disabled + ); throw new(); } @@ -63,7 +87,15 @@ public async Task TestAsyncObject(object request) public async Task TestTransactionNullable(Entity? entity) { await _transaction.CommitAsync(entity, entity => - entity.Update(Guid.NewGuid(), "test", "transaction func", 1, new("https://func.com"), new { transaction = "func" }, Status.Enabled) - ); + entity.Update( + guid: Guid.NewGuid(), + @string: "test", + stringData: "transaction func", + int32: 1, + uri: new("https://func.com"), + @dynamic: new { transaction = "func" }, + status: Status.Enabled + ) + ); } } From e99255c8574cf6288da721e033a5fca9b5448194 Mon Sep 17 00:00:00 2001 From: Sefer Mirza Date: Wed, 29 Nov 2023 16:07:06 +0300 Subject: [PATCH 20/25] review --- .../ServiceSpecExtensions.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs index 3ed01ce17..a992381ba 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs @@ -126,21 +126,22 @@ public static void ShouldHaveOneParameter(this MethodInfo source) #region Settings - public static void ASetting(this Mocker mockMe, - string? key = default, - string? value = default - ) => mockMe.ASetting(key: key ?? "Test:Configuration", value: value ?? "value"); - public static void ASetting(this Mocker mockMe, string? key = default, T? value = default + ) => mockMe.ASetting(key: key, value: $"{value}"); + + public static void ASetting(this Mocker mockMe, + string? key = default, + string? value = default ) { key ??= "Test:Configuration"; + value ??= "value"; var spec = (ServiceSpec)mockMe.Spec; - spec.Settings[key] = $"{value}"; + spec.Settings[key] = value; } internal static IConfiguration TheConfiguration(this Mocker mockMe, From bdf4eebf620d5b4a52b8d0a8f543e6d247bb6ffb Mon Sep 17 00:00:00 2001 From: Sefer Mirza Date: Wed, 29 Nov 2023 16:30:00 +0300 Subject: [PATCH 21/25] review changes --- .../ServiceSpecExtensions.cs | 2 +- .../RestApi/Analyzer/Singleton.generated.cs | 11 +++++++-- .../Configuration/MockingConfiguration.cs | 11 +++++++++ .../TestServiceSpecExtensions.cs | 23 ++++++++----------- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs index a992381ba..7109dd280 100644 --- a/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs +++ b/src/blueprints/Do.Blueprints.Service.Application/ServiceSpecExtensions.cs @@ -129,7 +129,7 @@ public static void ShouldHaveOneParameter(this MethodInfo source) public static void ASetting(this Mocker mockMe, string? key = default, T? value = default - ) => mockMe.ASetting(key: key, value: $"{value}"); + ) => mockMe.ASetting(key: key, value: $"{value}"); public static void ASetting(this Mocker mockMe, string? key = default, diff --git a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs index 2511a0877..0a1f261f0 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Singleton.generated.cs @@ -1,5 +1,6 @@ // This file will be auto-generated +using Do.Orm; using Microsoft.AspNetCore.Mvc; namespace Do.Test; @@ -54,14 +55,20 @@ public void TestException(bool handled) target.TestException(handled); } + public record TestTransactionNullableRequest(Guid? EntityId = default); + [HttpPost] [Produces("application/json")] [Route("singleton/test-transaction-nullable")] - public async Task TestTransactionNullable([FromBody] Entity entity = default) + public async Task TestTransactionNullable([FromBody] TestTransactionNullableRequest request) { var target = _serviceProvider.GetRequiredService(); - await target.TestTransactionNullable(entity); + await target.TestTransactionNullable( + entity: request.EntityId.HasValue + ? _serviceProvider.GetRequiredService>().SingleById(request.EntityId.Value) + : null + ); } [HttpPut] diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs index 5fdf25881..4c622fab6 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Configuration/MockingConfiguration.cs @@ -15,6 +15,17 @@ public void Mock_configuration_returns_mocked_settings_value() actual.ShouldBe(10); } + [Test] + public void Mock_configuration_returns_default_value_when_not_set() + { + MockMe.ASetting("Config"); + var configuration = GiveMe.The(); + + var actual = configuration.GetRequiredValue("Config"); + + actual.ShouldBe(0); + } + [TestCase(42)] [TestCase("value")] [TestCase(false)] diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 7444768ee..39c253c09 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -12,17 +12,14 @@ public static Entity AnEntity(this Stubber giveMe, Uri? uri = default, object? @dynamic = default, Status? status = default - ) - { - return giveMe - .A() - .With( - guid ?? Guid.NewGuid(), - @string ?? string.Empty, - stringData ?? string.Empty, - int32 ?? 0, uri ?? giveMe.AUrl(), - dynamic ?? new { }, - status ?? Status.Disabled - ); - } + ) => giveMe + .A() + .With( + guid ?? Guid.NewGuid(), + @string ?? string.Empty, + stringData ?? string.Empty, + int32 ?? 0, uri ?? giveMe.AUrl(), + dynamic ?? new { }, + status ?? Status.Disabled + ); } From 443b192463266cb6342f9e907bd36e2531bbc177 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 18:20:38 +0300 Subject: [PATCH 22/25] review, property mapping tests --- .../RestApi/Analyzer/Entity.generated.cs | 50 ++++++++- .../DataAccess/MappingProperties.cs | 92 +++++++++++++++ .../DataAccess/PersistingEntity.cs | 4 +- .../TestServiceSpecExtensions.cs | 9 +- .../Do.Test.Blueprints.Service/Entity.cs | 106 +++++++++++++++--- .../Do.Test.Blueprints.Service/Singleton.cs | 12 +- 6 files changed, 241 insertions(+), 32 deletions(-) create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs diff --git a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs index 56004dec4..6d7020ce7 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs @@ -13,13 +13,34 @@ public class EntityController public EntityController(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + public record ByRequest( + Guid Guid = default, + string String = default, + string StringData = default, + int Int32 = default, + Uri Uri = default, + object Dynamic = default, + Status Status = default, + DateTime DateTime = default + ); + [HttpGet] [Route("entities")] - public List By([FromQuery] string @string = default, [FromQuery] int? take = null, [FromQuery] int? skip = null) + public List By([FromQuery] ByRequest request, [FromQuery] int? take = null, [FromQuery] int? skip = null) { var target = _serviceProvider.GetRequiredService(); - var result = target.By(@string: @string, take: take, skip: skip); + var result = target.By( + guid: request.Guid, + @string: request.String, + stringData: request.StringData, + int32: request.Int32, + uri: request.Uri, + status: request.Status, + dateTime: request.DateTime, + take: take, + skip: skip + ); return result; } @@ -33,7 +54,16 @@ public Entity Get(Guid id) return target.SingleById(id); } - public record NewRequest(Guid Guid, string String, string StringData, int Int32, Uri Uri, object Dynamic, Status Status); + public record NewRequest( + Guid Guid = default, + string String = default, + string StringData = default, + int Int32 = default, + Uri Uri = default, + object Dynamic = default, + Status Status = default, + DateTime DateTime = default + ); [HttpPost] [Route("entities")] @@ -41,7 +71,7 @@ public Entity New([FromBody] NewRequest request) { var target = _serviceProvider.GetRequiredService(); - return target.With(request.Guid, request.String, request.StringData, request.Int32, request.Uri, request.Dynamic, request.Status); + return target.With(request.Guid, request.String, request.StringData, request.Int32, request.Uri, request.Dynamic, request.Status, request.DateTime); } [HttpDelete] @@ -53,7 +83,15 @@ public void Delete([FromRoute] Guid id) target.Delete(); } - public record UpdateRequest(Guid Guid, string String, string StringData, int Int32, Uri Uri, object Dynamic, Status Status, + public record UpdateRequest( + Guid Guid = default, + string String = default, + string StringData = default, + int Int32 = default, + Uri Uri = default, + object Dynamic = default, + Status Status = default, + DateTime DateTime = default, bool useTransaction = false, bool throwError = false ); @@ -64,7 +102,7 @@ public async Task Update([FromRoute] Guid id, [FromBody] UpdateRequest request) { var target = _serviceProvider.GetRequiredService>().SingleById(id); - await target.Update(request.Guid, request.String, request.StringData, request.Int32, request.Uri, request.Dynamic, request.Status, + await target.Update(request.Guid, request.String, request.StringData, request.Int32, request.Uri, request.Dynamic, request.Status, request.DateTime, useTransaction: request.useTransaction, throwError: request.throwError ); diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs new file mode 100644 index 000000000..0dc30562f --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs @@ -0,0 +1,92 @@ +namespace Do.Test.DataAccess; + +public class MappingProperties : TestServiceSpec +{ + [Test] + public async Task Guid() + { + var entity = GiveMe.An().With(guid: GiveMe.AGuid("EB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")); + entity.Guid.ShouldBe(GiveMe.AGuid("EB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")); + + await entity.Update(guid: GiveMe.AGuid("AB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")); + entity.Guid.ShouldBe(GiveMe.AGuid("AB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")); + + var actual = GiveMe.The().By(guid: GiveMe.AGuid("AB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")).FirstOrDefault(); + actual.ShouldBe(entity); + } + + [Test] + public async Task String() + { + var entity = GiveMe.An().With(@string: "string"); + entity.String.ShouldBe("string"); + + await entity.Update(@string: "test"); + entity.String.ShouldBe("test"); + + var actual = GiveMe.The().By(@string: "test").FirstOrDefault(); + actual.ShouldBe(entity); + } + + [Test] + public async Task String_data() + { + var entity = GiveMe.An().With(stringData: "string"); + entity.StringData.ShouldBe("string"); + + await entity.Update(stringData: "test"); + entity.StringData.ShouldBe("test"); + + var actual = GiveMe.The().By(stringData: "test").FirstOrDefault(); + actual.ShouldBe(entity); + } + + [Test] + public async Task Object() + { + var entity = GiveMe.An().With(dynamic: new { dynamic = "dynamic" }); + entity.Dynamic.ShouldBe(new { dynamic = "dynamic" }); + + await entity.Update(dynamic: new { update = "update" }); + entity.Dynamic.ShouldBe(new { update = "update" }); + } + + [Test] + public async Task Int() + { + var entity = GiveMe.An().With(int32: 5); + entity.Int32.ShouldBe(5); + + await entity.Update(int32: 1); + entity.Int32.ShouldBe(1); + + var actual = GiveMe.The().By(int32: 1).FirstOrDefault(); + actual.ShouldBe(entity); + } + + [Test] + public async Task Enum() + { + var entity = GiveMe.An().With(@enum: Status.Enabled); + entity.Enum.ShouldBe(Status.Enabled); + + await entity.Update(@enum: Status.Disabled); + entity.Enum.ShouldBe(Status.Disabled); + + var actual = GiveMe.The().By(status: Status.Disabled).FirstOrDefault(); + actual.ShouldBe(entity); + } + + [Test] + public async Task DateTime() + { + var entity = GiveMe.An().With(dateTime: System.DateTime.Parse("5/1/2008 8:30:52 AM")); + entity.DateTime.ShouldBe(System.DateTime.Parse("5/1/2008 8:30:52 AM")); + + await entity.Update(dateTime: System.DateTime.Parse("6/1/2008 8:30:52 AM")); + entity.DateTime.ShouldBe(System.DateTime.Parse("6/1/2008 8:30:52 AM")); + + var actual = GiveMe.The().By(dateTime: System.DateTime.Parse("6/1/2008 8:30:52 AM")).FirstOrDefault(); + actual.ShouldBe(entity); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs index e7f7cb75c..46bc07683 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/PersistingEntity.cs @@ -14,7 +14,7 @@ public void Created_entity_persists() int32: 0, uri: GiveMe.AUrl(), @dynamic: new { }, - status: Status.Disabled + @enum: Status.Disabled ); actual.ShouldBeInserted(); @@ -36,7 +36,7 @@ public void Object_user_type_supports_special_characters_to_be_used_within_strin var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" }); var entities = GiveMe.The(); - Func> task = () => entities.By(entity.String); + Func> task = () => entities.By(@string: entity.String); task.ShouldNotThrow(); } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 39c253c09..91531858f 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -11,15 +11,18 @@ public static Entity AnEntity(this Stubber giveMe, int? int32 = default, Uri? uri = default, object? @dynamic = default, - Status? status = default + Status? @enum = default, + DateTime? dateTime = default ) => giveMe .A() .With( guid ?? Guid.NewGuid(), @string ?? string.Empty, stringData ?? string.Empty, - int32 ?? 0, uri ?? giveMe.AUrl(), + int32 ?? 0, + uri ?? giveMe.AUrl(), dynamic ?? new { }, - status ?? Status.Disabled + @enum ?? Status.Disabled, + dateTime ?? DateTime.Now ); } diff --git a/test/blueprints/Do.Test.Blueprints.Service/Entity.cs b/test/blueprints/Do.Test.Blueprints.Service/Entity.cs index c3073315f..f4990f1f6 100644 --- a/test/blueprints/Do.Test.Blueprints.Service/Entity.cs +++ b/test/blueprints/Do.Test.Blueprints.Service/Entity.cs @@ -19,27 +19,74 @@ public Entity(IEntityContext context, ITransaction transaction) => public virtual int Int32 { get; protected set; } = default!; public virtual Uri Uri { get; protected set; } = default!; public virtual object Dynamic { get; protected set; } = default!; - public virtual Status Status { get; protected set; } = default!; + public virtual Status Enum { get; protected set; } = default!; + public virtual DateTime DateTime { get; protected set; } = default!; - public virtual Entity With(Guid guid, string @string, string stringData, int int32, Uri uri, object @dynamic, Status status) + public virtual Entity With( + Guid? guid = default, + string? @string = default, + string? stringData = default, + int? int32 = default, + Uri? uri = default, + object? @dynamic = default, + Status? @enum = default, + DateTime? dateTime = default + ) { - Set(guid, @string, stringData, int32, uri, @dynamic, status); + Set( + guid: guid, + @string: @string, + stringData: stringData, + int32: int32, + uri: uri, + @dynamic: @dynamic, + @enum: @enum, + dateTime: dateTime + ); return _context.Insert(this); } - public virtual async Task Update(Guid guid, string @string, string stringData, int int32, Uri uri, object @dynamic, Status status, + public virtual async Task Update( + Guid? guid = default, + string? @string = default, + string? stringData = default, + int? int32 = default, + Uri? uri = default, + object? @dynamic = default, + Status? @enum = default, + DateTime? dateTime = default, bool useTransaction = false, bool throwError = false ) { if (useTransaction) { - await _transaction.CommitAsync(this, @this => @this.Set(guid, @string, stringData, int32, uri, @dynamic, status)); + await _transaction.CommitAsync(this, @this => + @this.Set( + guid: guid, + @string: @string, + stringData: stringData, + int32: int32, + uri: uri, + @dynamic: @dynamic, + @enum: @enum, + dateTime: dateTime + ) + ); } else { - Set(guid, @string, stringData, int32, uri, @dynamic, status); + Set( + guid: guid, + @string: @string, + stringData: stringData, + int32: int32, + uri: uri, + @dynamic: @dynamic, + @enum: @enum, + dateTime: dateTime + ); } if (throwError) @@ -48,15 +95,25 @@ public virtual async Task Update(Guid guid, string @string, string stringData, i } } - protected virtual void Set(Guid guid, string @string, string stringData, int int32, Uri uri, object @dynamic, Status status) + protected virtual void Set( + Guid? guid = default, + string? @string = default, + string? stringData = default, + int? int32 = default, + Uri? uri = default, + object? @dynamic = default, + Status? @enum = default, + DateTime? dateTime = default + ) { - Guid = guid; - String = @string; - StringData = stringData; - Int32 = int32; - Uri = uri; - Dynamic = @dynamic; - Status = status; + Guid = guid ?? Guid; + String = @string ?? String; + StringData = stringData ?? StringData; + Int32 = int32 ?? Int32; + Uri = uri ?? Uri; + Dynamic = @dynamic ?? Dynamic; + Enum = @enum ?? Enum; + DateTime = dateTime ?? DateTime; } public virtual void Delete() @@ -73,13 +130,28 @@ public Entities(IQueryContext context) => _context = context; public List By( + Guid? guid = default, string? @string = default, + string? stringData = default, + int? int32 = default, + Uri? uri = default, + Status? status = default, + DateTime? dateTime = default, int? take = default, int? skip = default ) { - if (@string == default) { return _context.All(take: take, skip: skip); } - - return _context.By(e => e.String == @string, take: take, skip: skip); + return _context.By( + where: e => + (guid == default || e.Guid == guid) && + (@string == default || e.String == @string) && + (stringData == default || e.StringData == @stringData) && + (int32 == default || e.Int32 == int32) && + (uri == default || e.Uri == uri) && + (status == default || e.Enum == status) && + (dateTime == default || e.DateTime == dateTime), + take: take, + skip: skip + ); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs index 8b9e4944a..68d3f1896 100644 --- a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs +++ b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs @@ -41,7 +41,8 @@ await _transaction.CommitAsync(() => int32: 1, uri: new("https://action.com"), @dynamic: new { transaction = "action" }, - status: Status.Enabled + @enum: Status.Enabled, + dateTime: DateTime.Now ); }); @@ -58,7 +59,8 @@ public async Task TestTransactionFunc() int32: 1, uri: new("https://func.com"), @dynamic: new { transaction = "func" }, - status: Status.Enabled + @enum: Status.Enabled, + dateTime: DateTime.Now ) ); @@ -69,7 +71,8 @@ await entity.Update( int32: 2, uri: new("https://rollback.com"), @dynamic: new { rollback = "rollback" }, - status: Status.Disabled + @enum: Status.Disabled, + dateTime: DateTime.Now ); throw new(); @@ -94,7 +97,8 @@ await _transaction.CommitAsync(entity, entity => int32: 1, uri: new("https://func.com"), @dynamic: new { transaction = "func" }, - status: Status.Enabled + @enum: Status.Enabled, + dateTime: DateTime.Now ) ); } From eefd538d65f16cc376973dabf3034d21c6ffdf53 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 18:57:32 +0300 Subject: [PATCH 23/25] review --- .../RestApi/Analyzer/Entity.generated.cs | 29 +++++++++---------- .../DataAccess/MappingProperties.cs | 10 +++---- .../TestServiceSpecExtensions.cs | 2 +- .../Do.Test.Blueprints.Service/Singleton.cs | 8 ++--- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs index 6d7020ce7..e1c9108a0 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Application/RestApi/Analyzer/Entity.generated.cs @@ -14,14 +14,13 @@ public EntityController(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; public record ByRequest( - Guid Guid = default, - string String = default, - string StringData = default, - int Int32 = default, - Uri Uri = default, - object Dynamic = default, - Status Status = default, - DateTime DateTime = default + Guid guid = default, + string @string = default, + string stringData = default, + int int32 = default, + Uri uri = default, + Status status = default, + DateTime dateTime = default ); [HttpGet] @@ -31,13 +30,13 @@ public List By([FromQuery] ByRequest request, [FromQuery] int? take = nu var target = _serviceProvider.GetRequiredService(); var result = target.By( - guid: request.Guid, - @string: request.String, - stringData: request.StringData, - int32: request.Int32, - uri: request.Uri, - status: request.Status, - dateTime: request.DateTime, + guid: request.guid, + @string: request.@string, + stringData: request.stringData, + int32: request.int32, + uri: request.uri, + status: request.status, + dateTime: request.dateTime, take: take, skip: skip ); diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs index 0dc30562f..043ce7f67 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs @@ -80,13 +80,13 @@ public async Task Enum() [Test] public async Task DateTime() { - var entity = GiveMe.An().With(dateTime: System.DateTime.Parse("5/1/2008 8:30:52 AM")); - entity.DateTime.ShouldBe(System.DateTime.Parse("5/1/2008 8:30:52 AM")); + var entity = GiveMe.An().With(dateTime: new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); + entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); - await entity.Update(dateTime: System.DateTime.Parse("6/1/2008 8:30:52 AM")); - entity.DateTime.ShouldBe(System.DateTime.Parse("6/1/2008 8:30:52 AM")); + await entity.Update(dateTime: new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); + entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); - var actual = GiveMe.The().By(dateTime: System.DateTime.Parse("6/1/2008 8:30:52 AM")).FirstOrDefault(); + var actual = GiveMe.The().By(dateTime: new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)).FirstOrDefault(); actual.ShouldBe(entity); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 91531858f..00700e91f 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -23,6 +23,6 @@ public static Entity AnEntity(this Stubber giveMe, uri ?? giveMe.AUrl(), dynamic ?? new { }, @enum ?? Status.Disabled, - dateTime ?? DateTime.Now + dateTime ?? new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc) ); } diff --git a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs index 68d3f1896..d552b3d6f 100644 --- a/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs +++ b/test/blueprints/Do.Test.Blueprints.Service/Singleton.cs @@ -42,7 +42,7 @@ await _transaction.CommitAsync(() => uri: new("https://action.com"), @dynamic: new { transaction = "action" }, @enum: Status.Enabled, - dateTime: DateTime.Now + dateTime: _system.Now ); }); @@ -60,7 +60,7 @@ public async Task TestTransactionFunc() uri: new("https://func.com"), @dynamic: new { transaction = "func" }, @enum: Status.Enabled, - dateTime: DateTime.Now + dateTime: _system.Now ) ); @@ -72,7 +72,7 @@ await entity.Update( uri: new("https://rollback.com"), @dynamic: new { rollback = "rollback" }, @enum: Status.Disabled, - dateTime: DateTime.Now + dateTime: _system.Now ); throw new(); @@ -98,7 +98,7 @@ await _transaction.CommitAsync(entity, entity => uri: new("https://func.com"), @dynamic: new { transaction = "func" }, @enum: Status.Enabled, - dateTime: DateTime.Now + dateTime: _system.Now ) ); } From 3ce612f4c4e47d4d9e76d5c351bc863befcff006 Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 19:45:56 +0300 Subject: [PATCH 24/25] review, improve test coverage - add html coverage report generation console command to makefile --- Makefile | 3 + .../DataAccess/MappingProperties.cs | 10 +-- .../DataAccess/Transaction/CommitAsync.cs | 38 ----------- .../Database/TransactionalWork.cs | 63 +++++++++++++++++++ .../DependencyInjection/SystemNow.cs | 15 +++++ .../ExceptionHandling/HandlingExceptions.cs | 16 +++++ 6 files changed, 102 insertions(+), 43 deletions(-) delete mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/Database/TransactionalWork.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/SystemNow.cs create mode 100644 test/blueprints/Do.Test.Blueprints.Service.Test/ExceptionHandling/HandlingExceptions.cs diff --git a/Makefile b/Makefile index e56f99290..587cfdd33 100644 --- a/Makefile +++ b/Makefile @@ -22,3 +22,6 @@ run: fi test: dotnet test + +# dotnet test -c Release --collect:"XPlat Code Coverage" --logger trx --results-directory .coverage --settings test/runsettings.xml +# reportgenerator -reports:.coverage\0d84daea-0041-4f8d-a93c-51d3d348fa69\coverage.cobertura.xml;.coverage\d606db4f-8ea5-4e9f-a304-f37b22a1f34b\coverage.cobertura.xml -targetdir:.coverage/report \ No newline at end of file diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs index 043ce7f67..a7f960702 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs @@ -80,13 +80,13 @@ public async Task Enum() [Test] public async Task DateTime() { - var entity = GiveMe.An().With(dateTime: new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); - entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); + var entity = GiveMe.An().With(dateTime: new DateTime(year: 2023, month: 11, day: 29)); + entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 29)); - await entity.Update(dateTime: new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); - entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)); + await entity.Update(dateTime: new DateTime(year: 2023, month: 11, day: 30)); + entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 30)); - var actual = GiveMe.The().By(dateTime: new DateTime(year: 2023, month: 11, day: 30, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc)).FirstOrDefault(); + var actual = GiveMe.The().By(dateTime: new DateTime(year: 2023, month: 11, day: 30)).FirstOrDefault(); actual.ShouldBe(entity); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs deleted file mode 100644 index a66a762b8..000000000 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/Transaction/CommitAsync.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Do.Test.DataAccess.Transaction; - -public class CommitAsync : TestServiceSpec -{ - [Test] - public void Commit_async_takes_nullable_parameters() - { - var singleton = GiveMe.The(); - - var task = singleton.TestTransactionNullable(null); - - task.ShouldNotThrow(); - } - - [Test] - public void Commit_async_update_occurs_when_entity_is_not_null() - { - var entity = GiveMe.AnEntity(@string: "string"); - var singleton = GiveMe.The(); - - var task = singleton.TestTransactionNullable(entity); - - task.ShouldNotThrow(); - entity.String.ShouldNotBe("string"); - } - - [Test] - public void Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() - { - var singleton = GiveMe.The(); - var entities = GiveMe.The(); - - var task = singleton.TestTransactionAction(); - - task.ShouldThrow(); - entities.By().ShouldNotBeEmpty(); - } -} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/Database/TransactionalWork.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/Database/TransactionalWork.cs new file mode 100644 index 000000000..cb45fc585 --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/Database/TransactionalWork.cs @@ -0,0 +1,63 @@ +namespace Do.Test.Database; + +public class TransactionalWork : TestServiceSpec +{ + [Test] + public void Commit_async_takes_nullable_parameters() + { + var singleton = GiveMe.The(); + + var task = singleton.TestTransactionNullable(null); + + task.ShouldNotThrow(); + } + + [Test] + public void Commit_async_update_occurs_when_entity_is_not_null() + { + var entity = GiveMe.AnEntity(@string: "string"); + var singleton = GiveMe.The(); + + var task = singleton.TestTransactionNullable(entity); + + task.ShouldNotThrow(); + entity.String.ShouldNotBe("string"); + } + + [Test] + public async Task Transaction_is_skipped_during_tests() + { + var entity = GiveMe.AnEntity(@string: "old"); + + await entity.Update( + @string: "new", + useTransaction: true + ); + + entity.String.ShouldBe("new"); + } + + [Test(Description = "Actual behaviour is not testable, this test is included only for documentation and to improve coverage")] + public void Entity_created_by_a_transaction_committed_asynchronously_persists_when_an_error_occurs() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); + + var task = singleton.TestTransactionAction(); + + task.ShouldThrow(); + entities.By().ShouldNotBeEmpty(); + } + + [Test(Description = "Actual behaviour is not testable, this test is included only for documentation and to improve coverage")] + public void Only_the_updates_outside_of_transaction_are_rolled_back_when_an_error_occurs() + { + var singleton = GiveMe.The(); + var entities = GiveMe.The(); + + var task = singleton.TestTransactionFunc(); + + task.ShouldThrow(); + entities.By().ShouldNotBeEmpty(); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/SystemNow.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/SystemNow.cs new file mode 100644 index 000000000..b400083af --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DependencyInjection/SystemNow.cs @@ -0,0 +1,15 @@ +namespace Do.Test.DependencyInjection; + +public class SystemNow : TestServiceSpec +{ + [Test] + public void ISystem_is_injected_to_access_machine_time() + { + MockMe.TheSystem(now: GiveMe.ADateTime(year: 2023, month: 11, day: 29)); + var singleton = GiveMe.The(); + + var actual = singleton.GetNow(); + + actual.ShouldBe(GiveMe.ADateTime(year: 2023, month: 11, day: 29)); + } +} diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/ExceptionHandling/HandlingExceptions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/ExceptionHandling/HandlingExceptions.cs new file mode 100644 index 000000000..1f99a9a55 --- /dev/null +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/ExceptionHandling/HandlingExceptions.cs @@ -0,0 +1,16 @@ +using Do.ExceptionHandling; + +namespace Do.Test.ExceptionHandling; + +public class HandlingExceptions : TestServiceSpec +{ + [Test(Description = "Actual behaviour is not testable, this test is included only for documentation and to improve coverage")] + public void HandledException_is_handled_by_default() + { + var singleton = GiveMe.The(); + + var task = () => singleton.TestException(handled: true); + + task.ShouldThrow(); + } +} From 215301d676f94fe7bba6ee167e29a1997407c2cd Mon Sep 17 00:00:00 2001 From: alptuncs Date: Wed, 29 Nov 2023 19:49:35 +0300 Subject: [PATCH 25/25] review, minor changes --- .../DataAccess/MappingProperties.cs | 10 +++++----- .../TestServiceSpecExtensions.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs index a7f960702..3653b67da 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/DataAccess/MappingProperties.cs @@ -80,13 +80,13 @@ public async Task Enum() [Test] public async Task DateTime() { - var entity = GiveMe.An().With(dateTime: new DateTime(year: 2023, month: 11, day: 29)); - entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 29)); + var entity = GiveMe.An().With(dateTime: GiveMe.ADateTime(year: 2023, month: 11, day: 29)); + entity.DateTime.ShouldBe(GiveMe.ADateTime(year: 2023, month: 11, day: 29)); - await entity.Update(dateTime: new DateTime(year: 2023, month: 11, day: 30)); - entity.DateTime.ShouldBe(new DateTime(year: 2023, month: 11, day: 30)); + await entity.Update(dateTime: GiveMe.ADateTime(year: 2023, month: 11, day: 30)); + entity.DateTime.ShouldBe(GiveMe.ADateTime(year: 2023, month: 11, day: 30)); - var actual = GiveMe.The().By(dateTime: new DateTime(year: 2023, month: 11, day: 30)).FirstOrDefault(); + var actual = GiveMe.The().By(dateTime: GiveMe.ADateTime(year: 2023, month: 11, day: 30)).FirstOrDefault(); actual.ShouldBe(entity); } } diff --git a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs index 00700e91f..eaf3c7a8c 100644 --- a/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs +++ b/test/blueprints/Do.Test.Blueprints.Service.Test/TestServiceSpecExtensions.cs @@ -23,6 +23,6 @@ public static Entity AnEntity(this Stubber giveMe, uri ?? giveMe.AUrl(), dynamic ?? new { }, @enum ?? Status.Disabled, - dateTime ?? new DateTime(year: 2023, month: 11, day: 29, hour: 18, minute: 30, second: 5, kind: DateTimeKind.Utc) + dateTime ?? giveMe.ADateTime() ); }