protected override async Task <IList <TodoItemInfo> > ExecuteFlowStepsAsync(TodoItemQuery input, IPrincipal flowInitiator) { // Ensure that the application fetches data belonging to the current user only (usually the one initiating // the current flow). input.Owner = flowInitiator; return(await todoItemService.GetByQueryAsync(input)); }
protected override async Task <TodoItemInfo> ExecuteFlowStepsAsync(long input, IPrincipal flowInitiator) { var todoItemQuery = new TodoItemQuery { Id = input, // Ensure that the application fetches data belonging to the current user only (usually the one // initiating the current flow). Owner = flowInitiator }; IList <TodoItemInfo> todoItemInfos = await todoItemService.GetByQueryAsync(todoItemQuery); TodoItemInfo result = todoItemInfos.FirstOrDefault(); return(result); }
public async Task <ActionResult <TodoItemModel> > GetByIdAsync(long id) { var todoItemQuery = new TodoItemQuery { Id = id, Owner = User }; IList <TodoItemInfo> todoItemInfoList = await todoService.GetByQueryAsync(todoItemQuery).ConfigureAwait(false); TodoItemModel model = todoItemInfoList.Select(MapFrom).FirstOrDefault(); if (model == null) { return(NotFound()); } return(Ok(model)); }
public async IAsyncEnumerable <TodoItemModel> GetByQueryAsync([FromQuery] TodoItemQueryModel todoItemQueryModel) { var todoItemQuery = new TodoItemQuery { Id = todoItemQueryModel.Id, IsComplete = todoItemQueryModel.IsComplete, NamePattern = todoItemQueryModel.NamePattern, Owner = User, PageIndex = todoItemQueryModel.PageIndex, PageSize = todoItemQueryModel.PageSize, IsSortAscending = todoItemQueryModel.IsSortAscending, SortBy = todoItemQueryModel.SortBy }; IList <TodoItemInfo> todoItemInfos = await todoService.GetByQueryAsync(todoItemQuery).ConfigureAwait(false); foreach (TodoItemInfo todoItemInfo in todoItemInfos) { yield return(MapFrom(todoItemInfo)); } }
public async IAsyncEnumerable <TodoItemModel> GetByQueryAsync([FromQuery] TodoItemQueryModel todoItemQueryModel) { var todoItemQuery = new TodoItemQuery { Id = todoItemQueryModel.Id, IsComplete = todoItemQueryModel.IsComplete, NamePattern = todoItemQueryModel.NamePattern, Owner = User, PageIndex = todoItemQueryModel.PageIndex, PageSize = todoItemQueryModel.PageSize, IsSortAscending = todoItemQueryModel.IsSortAscending, SortBy = todoItemQueryModel.SortBy }; IList <TodoItemInfo> todoItemInfos = await fetchTodoItemsFlow.ExecuteAsync(todoItemQuery, User); foreach (TodoItemInfo todoItemInfo in todoItemInfos) { yield return(MapFrom(todoItemInfo)); } }
public Task <IList <TodoItemInfo> > GetByQueryAsync(TodoItemQuery todoItemQuery) { throw new EntityNotFoundException(todoItemQuery.GetType(), null); }
public IReadOnlyCollection <TodoItem> Handle(TodoItemQuery query) { return(_todoItems); }
public async Task ExecuteAsync_WhenOneFlowStepThrowsException_MustThrowException() { // Arrange string userName = $"test-user--{Guid.NewGuid():N}"; IIdentity identity = new GenericIdentity(userName); string[] roles = { $"role--{Guid.NewGuid():N}" }; IPrincipal flowInitiator = new GenericPrincipal(identity, roles); ITodoItemService todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); ILoggerFactory loggerFactory = testWebApplicationFactory.Services.GetRequiredService <ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger <ApplicationFlowServingTestingPurposes>(); string namePrefix = $"todo-item--{Guid.NewGuid():N}"; ITodoItemService localTodoItemService = todoItemService; // This flow is expected to fail since the service is unable to persist invalid models async Task <object> FlowExpectedToThrowExceptionAsync() { await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#1", Owner = flowInitiator }); await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#2", Owner = flowInitiator }); await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#3", Owner = flowInitiator }); return(null); } ApplicationFlowOptions applicationFlowOptions = testWebApplicationFactory.Services.GetRequiredService <ApplicationFlowOptions>(); var applicationFlow = new ApplicationFlowServingTestingPurposes(FlowExpectedToThrowExceptionAsync, applicationFlowOptions, logger); // Act Func <Task> executeAsyncCall = async() => await applicationFlow.ExecuteAsync(input : null, flowInitiator); // Assert using (new AssertionScope()) { await executeAsyncCall .Should() .ThrowExactlyAsync <ValidationException>("application flow must fail in case of an error"); var query = new TodoItemQuery { Owner = flowInitiator, NamePattern = $"{namePrefix}%" }; // Get a new instance of ITodoItemService service to ensure data will be fetched from // a new DbContext. todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); IList <TodoItemInfo> list = await todoItemService.GetByQueryAsync(query); list.Count.Should().Be(expected: 0, "the application flow failed to persist todo items"); } }
public async Task ExecuteAsync_WhenTransactionTimesOut_MustThrowException() { // Arrange TimeSpan transactionTimeOut = TimeSpan.FromMilliseconds(1); TimeSpan biggerTimeout = TimeSpan.FromMilliseconds(1000); string userName = $"test-user--{Guid.NewGuid():N}"; IIdentity identity = new GenericIdentity(userName); string[] roles = { $"role--{Guid.NewGuid():N}" }; IPrincipal flowInitiator = new GenericPrincipal(identity, roles); ITodoItemService todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); ILoggerFactory loggerFactory = testWebApplicationFactory.Services.GetRequiredService <ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger <ApplicationFlowServingTestingPurposes>(); string namePrefix = $"todo-item--{Guid.NewGuid():N}"; // This flow is expected to fail ITodoItemService localTodoItemService = todoItemService; async Task <object> FlowExpectedToFailAsync() { await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#1", IsComplete = false, Owner = flowInitiator }); await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#2", IsComplete = false, Owner = flowInitiator }); // Ensure this flow step will take more time to execute than the configured transaction timeout used // by the application flow. Task.Delay(biggerTimeout).Wait(); return(null); } var query = new TodoItemQuery { Owner = flowInitiator, NamePattern = $"{namePrefix}%" }; ApplicationFlowOptions applicationFlowOptions = testWebApplicationFactory.Services.GetRequiredService <ApplicationFlowOptions>(); // Ensure the application flow will use a very short timeout value for its transaction. applicationFlowOptions.TransactionOptions.Timeout = transactionTimeOut; var applicationFlow = new ApplicationFlowServingTestingPurposes(FlowExpectedToFailAsync, applicationFlowOptions, logger); // Act Func <Task> executeAsyncCall = async() => await applicationFlow.ExecuteAsync(input : null, flowInitiator); // Get a new instance of ITodoItemService service to ensure data will be fetched from // a new DbContext. todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); IList <TodoItemInfo> list = await todoItemService.GetByQueryAsync(query); // Assert using (new AssertionScope()) { await executeAsyncCall .Should() .ThrowExactlyAsync <TransactionAbortedException>( "application flow must fail in case of transaction timeout"); list.Count.Should().Be(expected: 0, "no entities must be created in the event of a transaction timeout"); } }
public async Task ExecuteAsync_WhenAllStepsSucceeds_MustSucceed() { // Arrange string userName = $"test-user--{Guid.NewGuid():N}"; IIdentity identity = new GenericIdentity(userName); string[] roles = { $"role--{Guid.NewGuid():N}" }; IPrincipal flowInitiator = new GenericPrincipal(identity, roles); ITodoItemService todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); ILoggerFactory loggerFactory = testWebApplicationFactory.Services.GetRequiredService <ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger <ApplicationFlowServingTestingPurposes>(); string namePrefix = $"todo-item--{Guid.NewGuid():N}"; // This flow is expected to succeed since the service is persisting valid models ITodoItemService localTodoItemService = todoItemService; async Task <object> FlowExpectedToSucceedAsync() { await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#1", IsComplete = false, Owner = flowInitiator }); await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#2", IsComplete = false, Owner = flowInitiator }); await localTodoItemService.AddAsync(new NewTodoItemInfo { Name = $"{namePrefix}--#3", IsComplete = false, Owner = flowInitiator }); return(null); } ApplicationFlowOptions applicationFlowOptions = testWebApplicationFactory.Services.GetRequiredService <ApplicationFlowOptions>(); var applicationFlow = new ApplicationFlowServingTestingPurposes(FlowExpectedToSucceedAsync, applicationFlowOptions, logger); // Act await applicationFlow.ExecuteAsync(input : null, flowInitiator); // Assert var query = new TodoItemQuery { Owner = flowInitiator, NamePattern = $"{namePrefix}%" }; // Get a new instance of ITodoItemService service to ensure data will be fetched from // a new DbContext. todoItemService = testWebApplicationFactory.Services.GetRequiredService <ITodoItemService>(); IList <TodoItemInfo> list = await todoItemService.GetByQueryAsync(query); list.Count.Should().Be(expected: 3, "several todo items have been previously created"); }