OrleansTestKit
OrleansTestKit copied to clipboard
Add support for transactional state facet
Since the release of Orleans 2.1.0 grains now support transactions.
For a grain to use transactions it should be instanciated with a ITransactionalState<TState> facet:
public AccountGrain(
[TransactionalState("balance", "TransactionStore")]
ITransactionalState<Balance> balance)
{
this.balance = balance ?? throw new ArgumentNullException(nameof(balance));
}
It would be great to be able to unit test grain with a transactionnal state facet with the test kit. Right now trying to get a grain with a ITransactionalState<TState> facet like so:
var grain = await Silo.CreateGrainAsync<AccountGrain>(Guid.NewGuid());
Is throwing this exception:
Orleans.Runtime.OrleansException : Attribute mapper Castle.Proxies.IAttributeToFactoryMapper`1Proxy failed to create a factory for grain type AccountGrain
at Orleans.Runtime.ConstructorArgumentFactory.ArgumentFactory.GetFactory[TMetadata](IServiceProvider services, ParameterInfo parameter, IFacetMetadata metadata, Type type) in D:\build\agent\_work\23\s\src\Orleans.Runtime\Facet\ConstructorArgumentFactory.cs:line 90
Here is a naive implementation that fulfil the ITransactionalState interface and enable testing such grains:
class TestTransactionalState<TState> : ITransactionalState<TState>
where TState : class, new()
{
private readonly TState _state = new TState();
public Task<TResult> PerformRead<TResult>(Func<TState, TResult> readFunction)
{
return Task.FromResult(readFunction(_state));
}
public Task<TResult> PerformUpdate<TResult>(Func<TState, TResult> updateFunction)
{
return Task.FromResult(updateFunction(_state));
}
}
Standalone usage example:
var state = new TestTransactionalState<Balance>();
var grain = new AccountGrain(state);
This implementation works but something integrated to the test kit would be better.
This is very similar to #55. We can support constructor injection of ITransactionalState<TState> mock objects by registering our own implementation of IAttributeToFactoryMapper<TransactionalStateAttribute> in the silo's dependency injection container.
Any progress on this? Would be a great feature!
@erikljung Not directly. I have a branch that adds the needed support for constructor injection, but I've only applied it to the state facet interfaces/classes.