Skip to content

Instantly share code, notes, and snippets.

@ashic
Created June 29, 2014 15:39
Show Gist options
  • Save ashic/f622d06d5b1a0fd46e6a to your computer and use it in GitHub Desktop.
Save ashic/f622d06d5b1a0fd46e6a to your computer and use it in GitHub Desktop.
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