Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue / Add Service Blueprint Tests #81

Merged
merged 25 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,19 @@ public async Task<TEntity> CommitAsync<TEntity>(Func<Task<TEntity>> action)
return result;
}

public async Task CommitAsync<TEntity>(TEntity entity, Action<TEntity> action)
public async Task CommitAsync<TEntity>(TEntity? entity, Action<TEntity> action)
{
if (entity is null) { return; }

action(entity);

await CommitAndBeginNewTransaction();
}

public async Task CommitAsync<TEntity>(TEntity entity, Func<TEntity, Task> action)
public async Task CommitAsync<TEntity>(TEntity? entity, Func<TEntity, Task> action)
{
if (entity is null) { return; }

await action(entity);

await CommitAndBeginNewTransaction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,19 @@ public async Task<TEntity> CommitAsync<TEntity>(Func<Task<TEntity>> action)
return await action();
}

public Task CommitAsync<TEntity>(TEntity entity, Action<TEntity> action)
public Task CommitAsync<TEntity>(TEntity? entity, Action<TEntity> action)
{
if (entity is null) { return Task.CompletedTask; }

action(entity);

return Task.CompletedTask;
}

public async Task CommitAsync<TEntity>(TEntity entity, Func<TEntity, Task> action)
public async Task CommitAsync<TEntity>(TEntity? entity, Func<TEntity, Task> action)
{
if (entity is null) { return; }

await action(entity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ public static void ShouldHaveOneParameter<T>(this MethodInfo source)

#region Settings

public static void ASetting<T>(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
Expand Down
4 changes: 2 additions & 2 deletions src/blueprints/Do.Blueprints.Service/Database/ITransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public interface ITransaction
Task<TEntity> CommitAsync<TEntity>(Func<TEntity> action);
Task<TEntity> CommitAsync<TEntity>(Func<Task<TEntity>> action);

Task CommitAsync<TEntity>(TEntity entity, Action<TEntity> action);
Task CommitAsync<TEntity>(TEntity entity, Func<TEntity, Task> action);
Task CommitAsync<TEntity>(TEntity? entity, Action<TEntity> action);
Task CommitAsync<TEntity>(TEntity? entity, Func<TEntity, Task> action);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
cihandeniz marked this conversation as resolved.
Show resolved Hide resolved
Status Status = default,
DateTime DateTime = default
cihandeniz marked this conversation as resolved.
Show resolved Hide resolved
);

[HttpGet]
[Route("entities")]
public List<Entity> By([FromQuery] string @string = default, [FromQuery] int? take = null, [FromQuery] int? skip = null)
public List<Entity> By([FromQuery] ByRequest request, [FromQuery] int? take = null, [FromQuery] int? skip = null)
{
var target = _serviceProvider.GetRequiredService<Entities>();

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;
}
Expand All @@ -33,15 +54,24 @@ 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")]
public Entity New([FromBody] NewRequest request)
{
var target = _serviceProvider.GetRequiredService<Entity>();

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]
Expand All @@ -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
);
Expand All @@ -64,7 +102,7 @@ public async Task Update([FromRoute] Guid id, [FromBody] UpdateRequest request)
{
var target = _serviceProvider.GetRequiredService<IQueryContext<Entity>>().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
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// This file will be auto-generated

using Do.Orm;
using Microsoft.AspNetCore.Mvc;

namespace Do.Test;
Expand Down Expand Up @@ -54,6 +55,22 @@ 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] TestTransactionNullableRequest request)
{
var target = _serviceProvider.GetRequiredService<Singleton>();

await target.TestTransactionNullable(
entity: request.EntityId.HasValue
? _serviceProvider.GetRequiredService<IQueryContext<Entity>>().SingleById(request.EntityId.Value)
: null
);
}

[HttpPut]
[Produces("application/json")]
[Route("singleton/test-async-object")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ public void Mock_configuration_returns_mocked_settings_value()
actual.ShouldBe(10);
}

[Test]
public void Mock_configuration_returns_default_value_when_not_set()
{
MockMe.ASetting<int>("Config");
var configuration = GiveMe.The<IConfiguration>();

var actual = configuration.GetRequiredValue<int>("Config");

actual.ShouldBe(0);
}

[TestCase(42)]
[TestCase("value")]
[TestCase(false)]
public void Mock_ASetting_value_parameter_is_generic<T>(T value)
{
MockMe.ASetting("Config", value);
var configuration = GiveMe.The<IConfiguration>();

var actual = configuration.GetRequiredValue<T>("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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace Do.Test.DataAccess;

public class MappingProperties : TestServiceSpec
{
[Test]
public async Task Guid()
{
var entity = GiveMe.An<Entity>().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<Entities>().By(guid: GiveMe.AGuid("AB8DD0A1-07B7-42EC-AAD3-14B2A623C01E")).FirstOrDefault();
actual.ShouldBe(entity);
}

[Test]
public async Task String()
{
var entity = GiveMe.An<Entity>().With(@string: "string");
entity.String.ShouldBe("string");

await entity.Update(@string: "test");
entity.String.ShouldBe("test");

var actual = GiveMe.The<Entities>().By(@string: "test").FirstOrDefault();
actual.ShouldBe(entity);
}

[Test]
public async Task String_data()
{
var entity = GiveMe.An<Entity>().With(stringData: "string");
entity.StringData.ShouldBe("string");

await entity.Update(stringData: "test");
entity.StringData.ShouldBe("test");

var actual = GiveMe.The<Entities>().By(stringData: "test").FirstOrDefault();
actual.ShouldBe(entity);
}

[Test]
public async Task Object()
{
var entity = GiveMe.An<Entity>().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<Entity>().With(int32: 5);
entity.Int32.ShouldBe(5);

await entity.Update(int32: 1);
entity.Int32.ShouldBe(1);

var actual = GiveMe.The<Entities>().By(int32: 1).FirstOrDefault();
actual.ShouldBe(entity);
}

[Test]
public async Task Enum()
{
var entity = GiveMe.An<Entity>().With(@enum: Status.Enabled);
entity.Enum.ShouldBe(Status.Enabled);

await entity.Update(@enum: Status.Disabled);
entity.Enum.ShouldBe(Status.Disabled);

var actual = GiveMe.The<Entities>().By(status: Status.Disabled).FirstOrDefault();
actual.ShouldBe(entity);
}

[Test]
public async Task DateTime()
{
var entity = GiveMe.An<Entity>().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<Entities>().By(dateTime: System.DateTime.Parse("6/1/2008 8:30:52 AM")).FirstOrDefault();
actual.ShouldBe(entity);
cihandeniz marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Do.Test.DataAccess;

public class PersistingEntity : TestServiceSpec
cihandeniz marked this conversation as resolved.
Show resolved Hide resolved
{
[Test]
public void Created_entity_persists()
{
var newEntity = GiveMe.A<Func<Entity>>();

var actual = newEntity().With(
guid: Guid.NewGuid(),
@string: string.Empty,
stringData: string.Empty,
int32: 0,
uri: GiveMe.AUrl(),
@dynamic: new { },
@enum: Status.Disabled
);

actual.ShouldBeInserted();
}

[Test]
public void Entity_is_deleted_successfully()
{
var entity = GiveMe.AnEntity();

entity.Delete();

entity.ShouldBeDeleted();
}

[Test]
public void Object_user_type_supports_special_characters_to_be_used_within_strings()
{
var entity = GiveMe.AnEntity(dynamic: new { test = "ğ€@test" });
var entities = GiveMe.The<Entities>();

Func<List<Entity>> task = () => entities.By(@string: entity.String);

task.ShouldNotThrow();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Do.Test.DataAccess.Transaction;

public class CommitAsync : TestServiceSpec
cihandeniz marked this conversation as resolved.
Show resolved Hide resolved
{
[Test]
public void Commit_async_takes_nullable_parameters()
{
var singleton = GiveMe.The<Singleton>();

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<Singleton>();

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<Singleton>();
var entities = GiveMe.The<Entities>();

var task = singleton.TestTransactionAction();

task.ShouldThrow<Exception>();
entities.By().ShouldNotBeEmpty();
}
}
Loading