Skip to content

Instantly share code, notes, and snippets.

@scrooby
Created February 3, 2017 11:21
Show Gist options
  • Save scrooby/aed0068c0331d5a183f3e7fcb097be69 to your computer and use it in GitHub Desktop.
Save scrooby/aed0068c0331d5a183f3e7fcb097be69 to your computer and use it in GitHub Desktop.
Sample NServiceBus saga SpecFlow test that results in event message going to the error queue with error message "Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)". Some of the code has been flattened for example purposes, but the test does run and results in the same error hitting the queue.
public class ReconciliationSubmissionSaga : Saga<ReconciliationSubmissionSagaData>,
IAmStartedByMessages<StartReconciliationSubmissionCommand>,
IHandleMessages<StoreManualAgreementReconciliationFailedEvent>,
...
{
...
public Task Handle(StoreManualAgreementReconciliationFailedEvent message, IMessageHandlerContext context)
{
Data.SagaState = "StoreManualAgreementReconciliationFailed";
Data.SagaStateCreateDate = DateTime.UtcNow();
return Task.CompletedTask;
}
...
}
Scenario: Store manual agreement reconciliation failed
Given I have a reconciliation submission saga
When I send a store manual agreement reconciliation failed event
Then the saga state should be updated to 'StoreManualAgreementReconciliationFailed'
public class ReconciliationSubmissionSagaData : ContainSagaData
{
public virtual Guid CorrelationId { get; set; }
public virtual DateTime RaisedOn { get; set; }
public virtual Guid BrokerUid { get; set; }
public virtual Guid ReconciliationUid { get; set; }
public virtual string CashReceiptDescription { get; set; }
public virtual int AgreementReconciliationCount { get; set; }
public virtual string SagaState { get; set; }
public virtual DateTime SagaStateCreateDate { get; set; }
}
[Given(@"I have a reconciliation submission saga")]
public void GivenIHaveAReconciliationSubmissionSaga()
{
correlationId = Guid.NewGuid();
var sagaData = fixture.Create<ReconciliationSubmissionSagaDataDto>();
var sql = "INSERT INTO dbo.ReconciliationSubmissionSagaData (Id, Originator, OriginalMessageId, CorrelationId, RaisedOn, BrokerUid, ReconciliationUid, CashReceiptDescription, AgreementReconciliationCount, SagaState, SagaStateCreateDate)" +
$"VALUES ('{sagaData.Id}', '{sagaData.Originator}', '{sagaData.OriginalMessageId}', '{correlationId}', GETDATE(), '{sagaData.BrokerUid}', '{sagaData.ReconciliationUid}', '{sagaData.CashReceiptDescription}', {sagaData.AgreementReconciliationCount}, '{sagaData.SagaState}', '{sagaData.SagaStateCreateDate.ToShortDateString()}')";
dapperHelper.Execute(c => c.Execute(sql));
}
[When(@"I send a store manual agreement reconciliation failed event")]
public void WhenISendAStoreManualAgreementReconciliationFailedEvent()
{
var message = fixture.Build<StoreManualAgreementReconciliationFailedEvent>()
.With(x => x.CorrelationId, correlationId)
.Create();
var endpointConfiguration = new EndpointConfiguration("ReconciliationSubmission.Host");
endpointConfiguration.UseSerialization<JsonSerializer>();
endpointConfiguration.UsePersistence<NHibernatePersistence>();
endpointConfiguration.EnableInstallers();
endpointConfiguration.ApplyCustomConventions();
var endpointInstance = Endpoint.Start(endpointConfiguration).ConfigureAwait(false).GetAwaiter().GetResult();
endpointInstance.Publish(message).GetAwaiter().GetResult();
endpointInstance.Stop().ConfigureAwait(false).GetAwaiter().GetResult();
}
[Then(@"the saga state should be updated to '(.*)'")]
public void ThenTheSagaStateShouldBeUpdatedTo(string expectedSagaState)
{
var sql = "SELECT * FROM dbo.ReconciliationSubmissionSagaData " +
$"WHERE CorrelationId = '{correlationId}' AND SagaState = '{expectedSagaState}'";
var sagaData = pollingHelper.WaitForResult(
() => dapperHelper.Execute(c => c.Query<ReconciliationSubmissionSagaDataDto>(sql).FirstOrDefault()),
data => data != null);
Assert.IsNotNull(sagaData);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment