/// <summary> /// Initializes a new instance of the <see cref="TransactionStepAdapter<TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>"/>class. /// </summary> /// <param name="original">The original step.</param> /// <param name="stepConverter">The step converter.</param> /// <param name="reverseStepConverter">The reversed step converter.</param> /// <param name="dataConverter">The data converter.</param> public TransactionStepAdapter( ITransactionStep <TStepIdFrom, TDataFrom> original, Func <TStepIdFrom, TStepIdTo> stepConverter, Func <TStepIdTo, TStepIdFrom> reverseStepConverter, Func <TDataTo, TDataFrom> dataConverter) { this.original = original ?? throw new ArgumentNullException(nameof(original)); this.stepConverter = stepConverter ?? throw new ArgumentNullException(nameof(stepConverter)); this.reverseStepConverter = reverseStepConverter ?? throw new ArgumentNullException(nameof(reverseStepConverter)); this.dataConverter = dataConverter ?? throw new ArgumentNullException(nameof(dataConverter)); this.stepAction = this.original.StepAction == null ? null : new Action <TDataTo, IStepTransactionSessionInfo <TStepIdTo> >((data, info) => this.original.StepAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(info, null, null, this.stepConverter, this.reverseStepConverter))); this.undoAction = this.original.UndoAction == null ? null : new Action <TDataTo, IUndoTransactionSessionInfo <TStepIdTo> >((data, info) => this.original.UndoAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(null, info, null, this.stepConverter, this.reverseStepConverter))); this.postAction = this.original.PostAction == null ? null : new Action <TDataTo, IPostTransactionSessionInfo <TStepIdTo> >((data, info) => this.original.PostAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(null, null, info, this.stepConverter, this.reverseStepConverter))); #if !NET35 && !NOASYNC this.asyncStepAction = this.original.AsyncStepAction == null ? null : new Func <TDataTo, IStepTransactionSessionInfo <TStepIdTo>, Task>(async(data, info) => await this.original.AsyncStepAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(info, null, null, this.stepConverter, this.reverseStepConverter))); this.asyncUndoAction = this.original.AsyncUndoAction == null ? null : new Func <TDataTo, IUndoTransactionSessionInfo <TStepIdTo>, Task>(async(data, info) => await this.original.AsyncUndoAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(null, info, null, this.stepConverter, this.reverseStepConverter))); this.asyncPostAction = this.original.AsyncPostAction == null ? null : new Func <TDataTo, IPostTransactionSessionInfo <TStepIdTo>, Task>(async(data, info) => await this.original.AsyncPostAction(this.dataConverter(data), new TransactionSessionInfoAdapter <TStepIdTo, TStepIdFrom>(null, null, info, this.stepConverter, this.reverseStepConverter))); #endif }
/// <summary> /// Inserts a step at an index. /// </summary> /// <param name="index">The index.</param> /// <param name="step">The step.</param> public void InsertAtIndex(int index, ITransactionStep <TStepId, TData> step) { lock (this.syncLock) { this.AssertCanAddStep(); this.steps.Insert(index, step); } }
/// <summary> /// Adds a step. /// </summary> /// <param name="step">The step to add.</param> /// <returns>The definition.</returns> public void Add(ITransactionStep <TStepId, TData> step) { lock (this.syncLock) { this.AssertCanAddStep(); this.steps.Add(step.Validate()); } }
/// <summary> /// Creates an adapter for the step. /// </summary> /// <typeparam name="TStepIdTo">The type of the destination step id.</typeparam> /// <typeparam name="TDataTo">The type of the destination data.</typeparam> /// <typeparam name="TStepIdFrom">The type of the original step id.</typeparam> /// <typeparam name="TDataFrom">The type of the source data.</typeparam> /// <param name="original">The original step.</param> /// <param name="stepConverter">The step converter.</param> /// <param name="reverseStepConverter">The reversed step converter.</param> /// <param name="dataConverter">The data converter.</param> /// <returns>The adapter for the step.</returns> public static ITransactionStep <TStepIdTo, TDataTo> Adapter <TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>( this ITransactionStep <TStepIdFrom, TDataFrom> step, Func <TStepIdFrom, TStepIdTo> stepConverter, Func <TStepIdTo, TStepIdFrom> reverseStepConverter, Func <TDataTo, TDataFrom> dataConverter) { return(new TransactionStepAdapter <TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>(step, stepConverter, reverseStepConverter, dataConverter)); }
/// <summary> /// Inserts a step after a specific step id. /// </summary> /// <param name="id">The step id.</param> /// <param name="step">The comparer.</param> /// <param name="idComparer">The step id comparer.</param> public void InsertAfter(TStepId id, ITransactionStep <TStepId, TData> step, IEqualityComparer <TStepId> idComparer = null) { lock (this.syncLock) { this.AssertCanAddStep(); int index = this.GetIndex(id, idComparer); this.steps.Insert(Math.Max(0, index + 1), step); } }
/// <summary> /// Adds an adapter for the step to the transaction. /// </summary> /// <typeparam name="TStepIdTo">The type of the destination step id.</typeparam> /// <typeparam name="TDataTo">The type of the destination data.</typeparam> /// <typeparam name="TStepIdFrom">The type of the original step id.</typeparam> /// <typeparam name="TDataFrom">The type of the source data.</typeparam> /// <param name="step">The original step.</param> /// <param name="stepConverter">The step converter.</param> /// <param name="reverseStepConverter">The reversed step converter.</param> /// <param name="dataConverter">The data converter.</param> /// <returns>The transaction.</returns> public static ITransaction <TStepIdTo, TDataTo> AddAdapter <TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>( this ITransaction <TStepIdTo, TDataTo> transaction, ITransactionStep <TStepIdFrom, TDataFrom> step, Func <TStepIdFrom, TStepIdTo> stepConverter, Func <TStepIdTo, TStepIdFrom> reverseStepConverter, Func <TDataTo, TDataFrom> dataConverter) { return(transaction.Add(step.Adapter(stepConverter, reverseStepConverter, dataConverter))); }
/// <summary> /// Inserts a step adapter at an index. /// </summary> /// <typeparam name="TStepIdTo">The type of the destination step id.</typeparam> /// <typeparam name="TDataTo">The type of the destination data.</typeparam> /// <typeparam name="TStepIdFrom">The type of the original step id.</typeparam> /// <typeparam name="TDataFrom">The type of the source data.</typeparam> /// <param name="index">The index.</param> /// <param name="step">The step.</param> /// <param name="stepConverter">The step converter.</param> /// <param name="reverseStepConverter">The reversed step converter.</param> /// <param name="dataConverter">The data converter.</param> /// <returns>The transaction.</returns> public static ITransaction <TStepIdTo, TDataTo> InsertAdapterAtIndex <TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>( this ITransaction <TStepIdTo, TDataTo> transaction, int index, ITransactionStep <TStepIdFrom, TDataFrom> step, Func <TStepIdFrom, TStepIdTo> stepConverter, Func <TStepIdTo, TStepIdFrom> reverseStepConverter, Func <TDataTo, TDataFrom> dataConverter) { return(transaction.InsertAtIndex(index, step.Adapter(stepConverter, reverseStepConverter, dataConverter))); }
public TransactionProcessor(ITransactionRepository transactionRepository, IAccountRepository accountRepository) { this.transactionSteps = new AccountNumberAValidation() .SetNext(new AccountNumberBValidation()) .SetNext(new AccountAValidation(accountRepository)) .SetNext(new AccountBValidation(accountRepository)) .SetNext(new TransactionCountValidation(transactionRepository)) .SetNext(new DuplicateTransactionValidation(transactionRepository)) .SetNext(new SaveTransaction(transactionRepository)); }
/// <summary> /// Inserts a step adapter after a specific step id. /// </summary> /// <typeparam name="TStepIdTo">The type of the destination step id.</typeparam> /// <typeparam name="TDataTo">The type of the destination data.</typeparam> /// <typeparam name="TStepIdFrom">The type of the original step id.</typeparam> /// <typeparam name="TDataFrom">The type of the source data.</typeparam> /// <param name="id">The step id.</param> /// <param name="step">The step.</param> /// <param name="stepConverter">The step converter.</param> /// <param name="reverseStepConverter">The reversed step converter.</param> /// <param name="dataConverter">The data converter.</param> /// <param name="idComparer">The step id comparer.</param> /// <returns>The transaction.</returns> public static ITransaction <TStepIdTo, TDataTo> InsertAdapterAfter <TStepIdTo, TDataTo, TStepIdFrom, TDataFrom>( this ITransaction <TStepIdTo, TDataTo> transaction, TStepIdTo id, ITransactionStep <TStepIdFrom, TDataFrom> step, Func <TStepIdFrom, TStepIdTo> stepConverter, Func <TStepIdTo, TStepIdFrom> reverseStepConverter, Func <TDataTo, TDataFrom> dataConverter, IEqualityComparer <TStepIdTo> idComparer = null) { return(transaction.InsertAfter(id, step.Adapter(stepConverter, reverseStepConverter, dataConverter), idComparer)); }
public static async Task ProcessPost <TStepId, TData>(SessionEndContext <TStepId, TData> context) #endif { ITransactionStep <TStepId, TData> currentStep = context.Session.StepEnumerator.CurrentStep; ITransactionSession <TStepId, TData> session = context.Session; Stopwatch watch = new Stopwatch(); try { watch.Start(); #if NET35 || NOASYNC currentStep.PostAction(session.StepEnumerator.Data, context.Session); #else if (currentStep.PostAction != null) { currentStep.PostAction(session.StepEnumerator.Data, context.Session); } else { await currentStep.AsyncPostAction(session.StepEnumerator.Data, context.Session); } #endif watch.Stop(); if (session.ShouldLogStepExecution()) { session.TransactionContext .Logger .LogExecutionTime( watch.Elapsed, "Transaction '{0}': execution time for post step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id); } } catch (Exception e) { watch.Stop(); string info = string.Format( "Transaction '{0}': an error occurred during processing post step action for step '{1}' with id '{2}', execution time '{3}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id, watch.Elapsed); session.TransactionContext.Logger.ErrorFormat(e, info); #if NET35 || NOASYNC SessionEndOperation.EndSession(context.AddError(e)); #else await SessionEndOperation.EndSession(context.AddError(e)); #endif } }
/// <summary> /// Gets an index of the step with a specific id. /// </summary> /// <param name="id">The id.</param> /// <param name="idComparer">The comparer.</param> /// <returns>The index of the step with the id, if not found returns <c>-1</c>.</returns> private int GetIndex(TStepId id, IEqualityComparer <TStepId> idComparer) { IEqualityComparer <TStepId> comparer = idComparer ?? EqualityComparer <TStepId> .Default; for (int i = 0; i < this.steps.Count; ++i) { ITransactionStep <TStepId, TData> step = this.steps[i]; if (comparer.Equals(step.Id, id)) { return(i); } } return(-1); }
/// <summary> /// Validates a transaction step. /// </summary> /// <typeparam name="TStepId">The type of the step id.</typeparam> /// <typeparam name="TData">The type of the transaction data.</typeparam> /// <param name="step">The step to validate.</param> public static ITransactionStep <TStepId, TData> Validate <TStepId, TData>(this ITransactionStep <TStepId, TData> step) { if (step == null) { throw new ArgumentNullException(nameof(step)); } if (step.StepAction == null #if !NET35 && !NOASYNC && step.AsyncStepAction == null #endif ) { throw new NotSupportedException(string.Format("Improper step data for id '{0}': No step action.", step.Id)); } #if !NET35 && !NOASYNC if (step.StepAction != null && step.AsyncStepAction != null) { throw new NotSupportedException(string.Format("Improper step data for id '{0}': '{1}' and '{2}' cannot be set simultaneously.", step.Id, nameof(step.StepAction), nameof(step.AsyncStepAction))); } if (step.UndoAction != null && step.AsyncUndoAction != null) { throw new NotSupportedException(string.Format("Improper step data for id '{0}': '{1}' and '{2}' cannot be set simultaneously.", step.Id, nameof(step.UndoAction), nameof(step.AsyncUndoAction))); } if (step.PostAction != null && step.AsyncPostAction != null) { throw new NotSupportedException(string.Format("Improper step data for id '{0}': '{1}' and '{2}' cannot be set simultaneously.", step.Id, nameof(step.PostAction), nameof(step.AsyncPostAction))); } #endif return(step); }
public void addStep(ITransactionStep step) { _steps.Add(step); }
/// <summary> /// Inserts a step before a specific step id. /// </summary> /// <param name="id">The step id.</param> /// <param name="step">The step.</param> /// <param name="idComparer">The step id comparer.</param> public ITransaction <TStepId, TData> InsertBefore(TStepId id, ITransactionStep <TStepId, TData> step, IEqualityComparer <TStepId> idComparer = null) { this.context.Definition.InsertBefore(id, step, idComparer); return(this); }
/// <summary> /// Inserts a step at an index. /// </summary> /// <param name="index">The index.</param> /// <param name="step">The step.</param> public ITransaction <TStepId, TData> InsertAtIndex(int index, ITransactionStep <TStepId, TData> step) { this.context.Definition.InsertAtIndex(index, step); return(this); }
/// <summary> /// Adds a step. /// </summary> /// <param name="step">The step to add.</param> /// <returns>The transaction.</returns> public ITransaction <TStepId, TData> Add(ITransactionStep <TStepId, TData> step) { this.context.Definition.Add(step); return(this); }
/// <summary> /// Fills the current step. /// </summary> public void FillStep() { this.CurrentStep = this.session.TransactionContext.Definition.GetByIndex(this.CurrentStepIndex); }
public static async Task ProcessUndo <TStepId, TData>(RunUndoContext <TStepId, TData> context) #endif { ITransactionStep <TStepId, TData> currentStep = context.Session.StepEnumerator.CurrentStep; ITransactionSession <TStepId, TData> session = context.Session; Stopwatch watch = new Stopwatch(); try { watch.Start(); #if NET35 || NOASYNC currentStep.UndoAction(session.StepEnumerator.Data, session); #else if (currentStep.UndoAction != null) { currentStep.UndoAction(session.StepEnumerator.Data, session); } else { await currentStep.AsyncUndoAction(session.StepEnumerator.Data, session); } #endif watch.Stop(); #if NET35 || NOASYNC context.Session.TransactionContext.SessionStorage.StepReceding(session); #else await context.Session.TransactionContext.SessionStorage.StepReceding(session); #endif if (session.ShouldLogStepExecution()) { session.TransactionContext .Logger .LogExecutionTime( watch.Elapsed, "Transaction '{0}': execution time for undo step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id); } } catch (Exception e) { watch.Stop(); string info = string.Format( "Transaction '{0}': an error occurred during processing undo step action for step '{1}' with id '{2}', execution time '{3}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id, watch.Elapsed); session.TransactionContext.Logger.ErrorFormat(e, info); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = context.Session, RunPostActions = false, Result = ResultType.Failed } .AddError(context.CaughtException) .AddError(e)); } }
public static async Task RunUndo <TStepId, TData>(RunUndoContext <TStepId, TData> context) #endif { while (context.ProcessStepPredicate(context.Session.StepEnumerator.CurrentStep)) { ITransactionStep <TStepId, TData> step = context.Session.StepEnumerator.CurrentStep; if (step == null) { if (context.NoSessionEnd) { #if NET35 || NOASYNC context.UndoFinishAction(); #else await context.UndoFinishAction(); #endif return; } #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { RunPostActions = false, Session = context.Session, Result = context.Result } .AddError(context.CaughtException)); return; } ITransactionSession <TStepId, TData> session = context.Session; if (session.Recovered && step.Settings.NotRunOnRecovered()) { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': ignoring the undo step action for step '{1}' with id '{2}' as the step cannot be executed on a recovered transaction.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MovePrevious(); continue; } #if NET35 || NOASYNC if (step.UndoAction == null) #else if (step.UndoAction == null && step.AsyncUndoAction == null) #endif { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': no undo step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MovePrevious(); continue; } IExecutor executor = step.UndoActionExecutor != null ? step.UndoActionExecutor : step.Settings.SameExecutorForAllActions() ? step.StepActionExecutor : null; if (executor != null && executor.ShouldRun) { #if NET35 || NOASYNC executor.Run(() => { ProcessUndoOperation.ProcessUndo(context); if (!session.Ended) { session.StepEnumerator.MovePrevious(); RunUndoOperation.RunUndo(context); } }); #else executor.Run(async() => { await ProcessUndoOperation.ProcessUndo(context); if (!session.Ended) { session.StepEnumerator.MovePrevious(); await RunUndoOperation.RunUndo(context); } }); #endif return; } else { #if NET35 || NOASYNC ProcessUndoOperation.ProcessUndo(context); #else await ProcessUndoOperation.ProcessUndo(context); #endif session.StepEnumerator.MovePrevious(); } } #if NET35 || NOASYNC context.UndoFinishAction(); #else await context.UndoFinishAction(); #endif }
public IOInputContinue <TInput, TOutput, TOutput> ContinueWith(ITransactionStep <TInput, TOutput> step) { Entities.Add(step); return(new IOInputContinueExecute <TInput, TOutput, TOutput>(this)); }
public OutputVoidContinue <TOriginalOutput> ContinueWith(ITransactionStep step) { Transaction.Entities.Add(step); return(this); }
public static async Task RunPost <TStepId, TData>(SessionEndContext <TStepId, TData> context) #endif { while (true) { ITransactionStep <TStepId, TData> step = context.Session.StepEnumerator.CurrentStep; if (step == null) { #if NET35 || NOASYNC SessionEndOperation.EndSession(context); #else await SessionEndOperation.EndSession(context); #endif return; } ITransactionSession <TStepId, TData> session = context.Session; if (session.Recovered && step.Settings.NotRunOnRecovered()) { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': ignoring the post step action for step '{1}' with id '{2}' as the step cannot be executed on a recovered transaction.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MoveNext(); continue; } #if NET35 || NOASYNC if (step.PostAction == null) #else if (step.PostAction == null && step.AsyncPostAction == null) #endif { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': no post step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MoveNext(); continue; } IExecutor executor = step.PostActionExecutor != null ? step.PostActionExecutor : step.Settings.SameExecutorForAllActions() ? step.StepActionExecutor : null; if (executor != null && executor.ShouldRun) { #if NET35 || NOASYNC executor.Run(() => { ProcessPostOperation.ProcessPost(context); if (!session.Ended) { session.StepEnumerator.MoveNext(); RunPostOperation.RunPost(context); } }); #else executor.Run(async() => { await ProcessPostOperation.ProcessPost(context); if (!session.Ended) { session.StepEnumerator.MoveNext(); await RunPostOperation.RunPost(context); } }); #endif return; } else { #if NET35 || NOASYNC ProcessPostOperation.ProcessPost(context); #else await ProcessPostOperation.ProcessPost(context); #endif session.StepEnumerator.MoveNext(); } } }
public static async Task RunSession <TStepId, TData>(ITransactionSession <TStepId, TData> session) #endif { while (true) { ITransactionStep <TStepId, TData> step = session.StepEnumerator.CurrentStep; if (step == null) { #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, RunPostActions = true, Result = ResultType.Success }); return; } #if NET35 || NOASYNC session.PrepareStep(); #else await session.PrepareStep(); #endif if (session.Ended) { return; } if (session.Recovered && step.Settings.NotRunOnRecovered()) { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': ignoring step '{1}' with id '{2}' as the step cannot be executed on a recovered transaction.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MoveNext(); continue; } session.TransactionContext .Logger .DebugFormat( "Transaction '{0}: running step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); IExecutor executor = session.StepEnumerator.CurrentStep.StepActionExecutor; if (executor != null && executor.ShouldRun) { #if NET35 || NOASYNC executor.Run(() => { session.ProcessStep(); if (!session.Ended) { RunSessionOperation.MoveToNextStep(session, true); } }); #else executor.Run(async() => { await session.ProcessStep(); if (!session.Ended) { await RunSessionOperation.MoveToNextStep(session, true); } }); #endif return; } else { #if NET35 || NOASYNC session.ProcessStep(); #else await session.ProcessStep(); #endif if (session.Ended) { return; } #if NET35 || NOASYNC RunSessionOperation.MoveToNextStep(session, false); #else await RunSessionOperation.MoveToNextStep(session, false); #endif } } }
ContinueWith <TOutput>(ITransactionStep <TRequiredInput, TOutput> step) { Transaction.Entities.Add(step); return(new IOInputContinue <TOriginalInput, TOutput>(Transaction)); }
public IOInputContinue <TStepOutput> ContinueWith <TStepOutput>( ITransactionStep <TRequiredInput, TStepOutput> step) { Transaction.Entities.Add(step); return(new IOInputContinue <TStepOutput>(Transaction)); }
public OutputVoidContinueExecute ContinueWith(ITransactionStep step) { Entities.Add(step); return(new OutputVoidContinueExecute(this)); }
public ITransactionStep SetNext(ITransactionStep handler) { nextHandler = handler; return(handler); }
ContinueWith <TStepOutput>(ITransactionStep <TInput, TStepOutput> step) { Entities.Add(step); return(new IOInputContinue <TInput, TOutput, TStepOutput>(this)); }
public void WhenCreateAdapter_ShouldCreateProperly() { // Arrange byte expectedData = 200; string adapterExpectedData = expectedData.ToString(CultureInfo.InvariantCulture); bool postActionExecuted = false; bool stepActionExecuted = false; bool undoActionExecuted = false; Mock <ITransactionStep <int, byte> > step = new Mock <ITransactionStep <int, byte> >(); step.SetupGet(x => x.Id) .Returns(123); step.SetupGet(x => x.Settings) .Returns((StepSettings)int.MaxValue); step.SetupGet(x => x.PostAction) .Returns((byte data, IPostTransactionSessionInfo <int> sessionInfo) => { postActionExecuted = true; data.Should().Be(expectedData); }); step.SetupGet(x => x.StepAction) .Returns((byte data, IStepTransactionSessionInfo <int> sessionInfo) => { stepActionExecuted = true; data.Should().Be(expectedData); sessionInfo.CurrentStepId.Should().Be(step.Object.Id); }); step.SetupGet(x => x.UndoAction) .Returns((byte data, IUndoTransactionSessionInfo <int> sessionInfo) => { undoActionExecuted = true; data.Should().Be(expectedData); sessionInfo.CurrentStepId.Should().Be(step.Object.Id); }); step.SetupGet(x => x.PostActionExecutor) .Returns(new Mock <IExecutor>().Object); step.SetupGet(x => x.StepActionExecutor) .Returns(new Mock <IExecutor>().Object); step.SetupGet(x => x.UndoActionExecutor) .Returns(new Mock <IExecutor>().Object); Mock <IStepTransactionSessionInfo <string> > stepInfo = new Mock <IStepTransactionSessionInfo <string> >(); stepInfo.SetupGet(x => x.CurrentStepId) .Returns(step.Object.Id.ToString(CultureInfo.InvariantCulture)); stepInfo.SetupGet(x => x.Cancelled) .Returns(true); stepInfo.SetupGet(x => x.Recovered) .Returns(true); stepInfo.SetupGet(x => x.SessionId) .Returns(Guid.NewGuid()); stepInfo.SetupGet(x => x.StartTimestamp) .Returns(DateTime.Now); Mock <IUndoTransactionSessionInfo <string> > undoInfo = stepInfo.As <IUndoTransactionSessionInfo <string> >(); Mock <IPostTransactionSessionInfo <string> > postInfo = undoInfo.As <IPostTransactionSessionInfo <string> >(); ITransactionStep <string, string> adapter = step.Object.Adapter <string, string, int, byte>(id => id.ToString(), idString => int.Parse(idString), data => byte.Parse(data)); // Act adapter.PostAction(adapterExpectedData, postInfo.Object); // Assert postActionExecuted.Should().BeTrue(); // Act adapter.StepAction(adapterExpectedData, stepInfo.Object); // Assert stepActionExecuted.Should().BeTrue(); // Act adapter.UndoAction(adapterExpectedData, undoInfo.Object); // Assert undoActionExecuted.Should().BeTrue(); // Assert int.Parse(adapter.Id).Should().Be(step.Object.Id); adapter.Settings.Should().Be(step.Object.Settings); adapter.PostActionExecutor.Should().BeSameAs(step.Object.PostActionExecutor); adapter.StepActionExecutor.Should().BeSameAs(step.Object.StepActionExecutor); adapter.UndoActionExecutor.Should().BeSameAs(step.Object.UndoActionExecutor); }