Example #1
0
 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));
            }
        }
Example #5
0
        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);
 }
Example #7
0
 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");
        }