Skip to content

Commit bc1de6a

Browse files
author
Bart Koelman
committed
Added tests for Transactional Outbox pattern and fire-and-forget
1 parent f297212 commit bc1de6a

33 files changed

+3288
-0
lines changed

JsonApiDotNetCore.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ $left$ = $right$;</s:String>
621621
<s:Boolean x:Key="/Default/UserDictionary/Words/=Assignee/@EntryIndexedValue">True</s:Boolean>
622622
<s:Boolean x:Key="/Default/UserDictionary/Words/=Injectables/@EntryIndexedValue">True</s:Boolean>
623623
<s:Boolean x:Key="/Default/UserDictionary/Words/=linebreaks/@EntryIndexedValue">True</s:Boolean>
624+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Microservices/@EntryIndexedValue">True</s:Boolean>
624625
<s:Boolean x:Key="/Default/UserDictionary/Words/=navigations/@EntryIndexedValue">True</s:Boolean>
625626
<s:Boolean x:Key="/Default/UserDictionary/Words/=playlists/@EntryIndexedValue">True</s:Boolean>
626627
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rewriter/@EntryIndexedValue">True</s:Boolean>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using Bogus;
3+
using TestBuildingBlocks;
4+
5+
// @formatter:wrap_chained_method_calls chop_always
6+
// @formatter:keep_existing_linebreaks true
7+
8+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices
9+
{
10+
internal sealed class DomainFakers : FakerContainer
11+
{
12+
private readonly Lazy<Faker<DomainUser>> _lazyDomainUserFaker = new Lazy<Faker<DomainUser>>(() =>
13+
new Faker<DomainUser>()
14+
.UseSeed(GetFakerSeed())
15+
.RuleFor(domainUser => domainUser.LoginName, faker => faker.Person.UserName)
16+
.RuleFor(domainUser => domainUser.DisplayName, faker => faker.Person.FullName));
17+
18+
private readonly Lazy<Faker<DomainGroup>> _lazyDomainGroupFaker = new Lazy<Faker<DomainGroup>>(() =>
19+
new Faker<DomainGroup>()
20+
.UseSeed(GetFakerSeed())
21+
.RuleFor(domainGroup => domainGroup.Name, faker => faker.Commerce.Department()));
22+
23+
public Faker<DomainUser> DomainUser => _lazyDomainUserFaker.Value;
24+
public Faker<DomainGroup> DomainGroup => _lazyDomainGroupFaker.Value;
25+
}
26+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using JetBrains.Annotations;
4+
using JsonApiDotNetCore.Resources;
5+
using JsonApiDotNetCore.Resources.Annotations;
6+
7+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices
8+
{
9+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
10+
public sealed class DomainGroup : Identifiable<Guid>
11+
{
12+
[Attr]
13+
public string Name { get; set; }
14+
15+
[HasMany]
16+
public ISet<DomainUser> Users { get; set; }
17+
}
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using JsonApiDotNetCore.Configuration;
3+
using JsonApiDotNetCore.Controllers;
4+
using JsonApiDotNetCore.Services;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices
8+
{
9+
public sealed class DomainGroupsController : JsonApiController<DomainGroup, Guid>
10+
{
11+
public DomainGroupsController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<DomainGroup, Guid> resourceService)
12+
: base(options, loggerFactory, resourceService)
13+
{
14+
}
15+
}
16+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.ComponentModel.DataAnnotations;
3+
using JetBrains.Annotations;
4+
using JsonApiDotNetCore.Resources;
5+
using JsonApiDotNetCore.Resources.Annotations;
6+
7+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices
8+
{
9+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
10+
public sealed class DomainUser : Identifiable<Guid>
11+
{
12+
[Attr]
13+
[Required]
14+
public string LoginName { get; set; }
15+
16+
[Attr]
17+
public string DisplayName { get; set; }
18+
19+
[HasOne]
20+
public DomainGroup Group { get; set; }
21+
}
22+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using JsonApiDotNetCore.Configuration;
3+
using JsonApiDotNetCore.Controllers;
4+
using JsonApiDotNetCore.Services;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices
8+
{
9+
public sealed class DomainUsersController : JsonApiController<DomainUser, Guid>
10+
{
11+
public DomainUsersController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<DomainUser, Guid> resourceService)
12+
: base(options, loggerFactory, resourceService)
13+
{
14+
}
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using JetBrains.Annotations;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices.FireAndForgetDelivery
5+
{
6+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
7+
public sealed class FireForgetDbContext : DbContext
8+
{
9+
public DbSet<DomainUser> Users { get; set; }
10+
public DbSet<DomainGroup> Groups { get; set; }
11+
12+
public FireForgetDbContext(DbContextOptions<FireForgetDbContext> options)
13+
: base(options)
14+
{
15+
}
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using JetBrains.Annotations;
5+
using JsonApiDotNetCore.Configuration;
6+
using JsonApiDotNetCore.Middleware;
7+
using JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices.Messages;
8+
9+
namespace JsonApiDotNetCoreExampleTests.IntegrationTests.Microservices.FireAndForgetDelivery
10+
{
11+
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
12+
public sealed class FireForgetGroupDefinition : MessagingGroupDefinition
13+
{
14+
private readonly MessageBroker _messageBroker;
15+
private DomainGroup _groupToDelete;
16+
17+
public FireForgetGroupDefinition(IResourceGraph resourceGraph, FireForgetDbContext dbContext, MessageBroker messageBroker)
18+
: base(resourceGraph, dbContext.Users, dbContext.Groups)
19+
{
20+
_messageBroker = messageBroker;
21+
}
22+
23+
public override async Task OnWritingAsync(DomainGroup group, OperationKind operationKind, CancellationToken cancellationToken)
24+
{
25+
if (operationKind == OperationKind.DeleteResource)
26+
{
27+
_groupToDelete = await base.GetGroupToDeleteAsync(group.Id, cancellationToken);
28+
}
29+
}
30+
31+
public override Task OnWriteSucceededAsync(DomainGroup group, OperationKind operationKind, CancellationToken cancellationToken)
32+
{
33+
return FinishWriteAsync(group, operationKind, cancellationToken);
34+
}
35+
36+
protected override Task FlushMessageAsync(OutgoingMessage message, CancellationToken cancellationToken)
37+
{
38+
return _messageBroker.PostMessageAsync(message, cancellationToken);
39+
}
40+
41+
protected override Task<DomainGroup> GetGroupToDeleteAsync(Guid groupId, CancellationToken cancellationToken)
42+
{
43+
return Task.FromResult(_groupToDelete);
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)