Created
June 29, 2014 15:39
-
-
Save ashic/f622d06d5b1a0fd46e6a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using dokimi.core; | |
using dokimi.core.dokimi.core.Specs.MessageBased; | |
using dokimi.core.Specs.MessageBased; | |
using dokimi.nunit; | |
using Infura; | |
using Infura.EventSourcing; | |
namespace SpecsDemo | |
{ | |
public abstract class MySpec : NUnitSpecificationTest | |
{ | |
} | |
public class account_test : MySpec | |
{ | |
public Specification should_register_overdraft_attempt() | |
{ | |
var id = Guid.NewGuid(); | |
var spec = Specifications.Catalog | |
.MessageBasedSpecification("account", "overdrafts") | |
.NoHistory() | |
.When(new RegisterAccount(id, 300M, "john")) | |
.Then<AccountRegistered>(x => x.AccountId == id) | |
.Wireup(sink => | |
{ | |
var es = new InMemoryEventStore(); | |
es.AdjustDispatcher(x => sink(x.EventData)); | |
var repo = new EventStoreRepository(es); | |
var handler = new AccountHandler(repo); | |
var router = Router.Create() | |
.Route<RegisterAccount>(handler.Handle) | |
; | |
return router; | |
}); | |
return spec; | |
} | |
} | |
public class AccountHandler | |
{ | |
private readonly Repository _repo; | |
public AccountHandler(Repository repo) | |
{ | |
_repo = repo; | |
} | |
public void Handle(RegisterAccount command) | |
{ | |
var account = new Account(command.AccountId, command.InitialBalance, command.AccountHolder); | |
_repo.Save(account); | |
} | |
public void Handle(DebitAccount command) | |
{ | |
var account = _repo.GetById<Account>(command.Id); | |
account.Debit(command.Amount); | |
_repo.Save(account); | |
} | |
} | |
public class RegisterAccount | |
{ | |
public Guid AccountId { get; private set; } | |
public decimal InitialBalance { get; private set; } | |
public string AccountHolder { get; private set; } | |
public RegisterAccount(Guid accountId, decimal initialBalance, string accountHolder) | |
{ | |
AccountId = accountId; | |
InitialBalance = initialBalance; | |
AccountHolder = accountHolder; | |
} | |
} | |
public class Account : Aggregate | |
{ | |
private decimal _balance; | |
private int _attempts; | |
private bool _isLocked; | |
protected Account() | |
{ | |
} | |
public Account(Guid accountId, decimal initialBalance, string accountHolder) | |
: base(accountId) | |
{ | |
Apply(new AccountRegistered(accountId, initialBalance, accountHolder)); | |
} | |
public void Debit(decimal amount) | |
{ | |
if (_isLocked) | |
throw new AccountIsLockedException((Guid)Id); | |
if (amount > _balance) | |
{ | |
Apply(new OverdraftAttempted((Guid)Id)); | |
if (_attempts == 2) | |
Apply(new AccountLocked((Guid)Id)); | |
} | |
else | |
{ | |
Apply(new AccountDebited((Guid)Id, amount, _balance, _balance - amount)); | |
} | |
} | |
private void UpdateFrom(AccountRegistered e) | |
{ | |
_balance = e.Balance; | |
} | |
private void UpdateFrom(AccountDebited e) | |
{ | |
_attempts = 0; | |
_balance = e.NewBalance; | |
} | |
private void UpdateFrom(AccountLocked e) | |
{ | |
_isLocked = true; | |
} | |
public class AccountIsLockedException : Exception | |
{ | |
public AccountIsLockedException(Guid id) | |
{ | |
} | |
} | |
} | |
} | |
public class AccountRegistered | |
{ | |
public Guid AccountId { get; private set; } | |
public decimal Balance { get; private set; } | |
public string AccountHolder { get; private set; } | |
public AccountRegistered(Guid accountId, decimal balance, string accountHolder) | |
{ | |
AccountId = accountId; | |
Balance = balance; | |
AccountHolder = accountHolder; | |
} | |
} | |
public class AccountDebited | |
{ | |
public Guid Id { get; private set; } | |
public decimal Amount { get; private set; } | |
public decimal OldBalnce { get; private set; } | |
public decimal NewBalance { get; private set; } | |
public AccountDebited(Guid id, decimal amount, decimal oldBalnce, decimal newBalance) | |
{ | |
Id = id; | |
Amount = amount; | |
OldBalnce = oldBalnce; | |
NewBalance = newBalance; | |
} | |
} | |
public class DebitAccount | |
{ | |
public Guid Id { get; private set; } | |
public decimal Amount { get; private set; } | |
public DebitAccount(Guid id, decimal amount) | |
{ | |
Id = id; | |
Amount = amount; | |
} | |
} | |
public class OverdraftAttempted | |
{ | |
public Guid AccountId { get; private set; } | |
public OverdraftAttempted(Guid accountId) | |
{ | |
AccountId = accountId; | |
} | |
} | |
public class AccountLocked | |
{ | |
public Guid AccountId { get; private set; } | |
public AccountLocked(Guid accountId) | |
{ | |
AccountId = accountId; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment