public void Initialize()
        {
            this.requesterSecurity = new Mock <IRequesterSecurity>();
            this.requesterSecurity.SetupFor(Requester);

            // Mock potentially side-effecting components with strict behaviour.
            this.connectionFactory = new Mock <IFifthweekDbConnectionFactory>(MockBehavior.Strict);

            this.target = new ReorderQueueCommandHandler(this.requesterSecurity.Object, this.connectionFactory.Object);
        }
        private async Task <ExpectedSideEffects> TestExpectedQueueOrderAsync(TestDatabaseContext testDatabase, IReadOnlyList <Post> validSuperset, ReorderQueueCommand command)
        {
            this.target = new ReorderQueueCommandHandler(this.requesterSecurity.Object, testDatabase);

            await testDatabase.TakeSnapshotAsync();

            await this.target.HandleAsync(command);

            if (validSuperset.Count == 0)
            {
                return(ExpectedSideEffects.None);
            }

            // Posts that are both valid for update, and have been requested to be updated by the command.
            var allowedUpdates = validSuperset.Where(_ => command.NewPartialQueueOrder.Any(id => id.Value == _.Id)).ToArray();

            // Descending range of live dates for these posts.
            var expectedDateRange = allowedUpdates.Select(_ => _.LiveDate).OrderByDescending(_ => _).ToArray();

            // Re-assign live dates in order specified by command.
            var dateIndex       = 0;
            var expectedUpdates = new List <Post>();

            foreach (var postId in command.NewPartialQueueOrder)
            {
                // Request may contain IDs that are not valid for update, so we ignore these, as the implementation should.
                var allowedUpdate = allowedUpdates.SingleOrDefault(_ => _.Id == postId.Value);
                if (allowedUpdate != null)
                {
                    var newLiveDate = expectedDateRange[dateIndex++];
                    if (allowedUpdate.LiveDate == newLiveDate)
                    {
                        continue;
                    }

                    // Sometimes the live date may not have changed.
                    allowedUpdate.LiveDate = newLiveDate;
                    expectedUpdates.Add(allowedUpdate);
                }
            }

            if (expectedUpdates.Count == 0)
            {
                throw new Exception(
                          "It is unlikely that all posts will keep their original live date after being shuffled. " +
                          "Please check test code. If all is good and this is coincidental, then simply change the random seed number.");
            }

            return(new ExpectedSideEffects
            {
                Updates = expectedUpdates
            });
        }
        public async Task ItShouldBeIdempotent()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new ReorderQueueCommandHandler(this.requesterSecurity.Object, testDatabase);

                var validPosts             = await this.CreateValidQueueCandidatesAsync(testDatabase);
                var attemptedNewQueueOrder = GetRandomSubset(validPosts);
                var command = new ReorderQueueCommand(Requester, QueueId, attemptedNewQueueOrder);
                await this.target.HandleAsync(command);
                await testDatabase.TakeSnapshotAsync();

                await this.target.HandleAsync(command);

                return(ExpectedSideEffects.None);
            });
        }