public async Task WhenRegisteringWithNonUniqueUsername_ItShouldThrowAnException()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new RegisterUserDbStatement(this.userManager.Object, testDatabase, this.requestSnapshot);

                var hashedPassword = RegistrationData.Password + "1";
                this.passwordHasher.Setup(v => v.HashPassword(RegistrationData.Password.Value)).Returns(hashedPassword);

                await this.CreateUserAsync(testDatabase, RegistrationData.Username.Value, RegistrationData.Email + "1");

                await testDatabase.TakeSnapshotAsync();

                var exception = await ExpectedException.GetExceptionAsync <RecoverableException>(() =>
                {
                    return(this.target.ExecuteAsync(
                               UserId,
                               RegistrationData.Username,
                               RegistrationData.Email,
                               RegistrationData.ExampleWork,
                               RegistrationData.Password,
                               TimeStamp));
                });

                Assert.IsNotNull(exception);
                Assert.IsTrue(exception.Message.Contains("username"));

                return(ExpectedSideEffects.TransactionAborted);
            });
        }
        public async Task WhenCalledTwice_ItShouldBeIdempotent()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new RegisterUserDbStatement(this.userManager.Object, testDatabase, this.requestSnapshot);

                var hashedPassword = RegistrationData.Password + "1";
                this.passwordHasher.Setup(v => v.HashPassword(RegistrationData.Password.Value)).Returns(hashedPassword);

                await this.target.ExecuteAsync(
                    UserId,
                    RegistrationData.Username,
                    RegistrationData.Email,
                    RegistrationData.ExampleWork,
                    RegistrationData.Password,
                    TimeStamp);

                await testDatabase.TakeSnapshotAsync();

                await this.target.ExecuteAsync(
                    UserId,
                    RegistrationData.Username,
                    RegistrationData.Email,
                    RegistrationData.ExampleWork,
                    RegistrationData.Password,
                    TimeStamp);

                return(ExpectedSideEffects.None);
            });
        }
        public async Task WhenRegisteringANewUser_ItShouldAbortUpdateIfSnapshotFails()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new RegisterUserDbStatement(this.userManager.Object, testDatabase, this.requestSnapshot);

                var hashedPassword = RegistrationData.Password + "1";
                this.passwordHasher.Setup(v => v.HashPassword(RegistrationData.Password.Value)).Returns(hashedPassword);

                await testDatabase.TakeSnapshotAsync();

                this.requestSnapshot.ThrowException();

                await ExpectedException.AssertExceptionAsync <SnapshotException>(
                    () => this.target.ExecuteAsync(
                        UserId,
                        RegistrationData.Username,
                        RegistrationData.Email,
                        RegistrationData.ExampleWork,
                        RegistrationData.Password,
                        TimeStamp));

                return(ExpectedSideEffects.TransactionAborted);
            });
        }
        public void TestInitialize()
        {
            this.userManager    = new Mock <IUserManager>();
            this.passwordHasher = new Mock <IPasswordHasher>();
            this.userManager.Setup(v => v.PasswordHasher).Returns(this.passwordHasher.Object);
            this.requestSnapshot = new MockRequestSnapshotService();

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

            this.target = new RegisterUserDbStatement(this.userManager.Object, this.connectionFactory.Object, this.requestSnapshot);
        }
        public async Task WhenRegisteringANewUser_ItShouldRequestSnapshotAfterUpdate()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                var trackingDatabase = new TrackingConnectionFactory(testDatabase);
                this.target          = new RegisterUserDbStatement(this.userManager.Object, trackingDatabase, this.requestSnapshot);

                var hashedPassword = RegistrationData.Password + "1";
                this.passwordHasher.Setup(v => v.HashPassword(RegistrationData.Password.Value)).Returns(hashedPassword);

                await testDatabase.TakeSnapshotAsync();

                this.requestSnapshot.VerifyConnectionDisposed(trackingDatabase);

                await this.target.ExecuteAsync(
                    UserId,
                    RegistrationData.Username,
                    RegistrationData.Email,
                    RegistrationData.ExampleWork,
                    RegistrationData.Password,
                    TimeStamp);

                this.requestSnapshot.VerifyCalledWith(UserId, SnapshotType.Subscriber);

                var expectedUser = new FifthweekUser
                {
                    Id                  = UserId.Value,
                    UserName            = RegistrationData.Username.Value,
                    Email               = RegistrationData.Email.Value,
                    ExampleWork         = RegistrationData.ExampleWork,
                    RegistrationDate    = TimeStamp,
                    LastSignInDate      = SqlDateTime.MinValue.Value,
                    LastAccessTokenDate = SqlDateTime.MinValue.Value,
                    PasswordHash        = hashedPassword,
                };

                return(new ExpectedSideEffects
                {
                    Insert = new WildcardEntity <FifthweekUser>(expectedUser)
                    {
                        Expected = actual =>
                        {
                            expectedUser.SecurityStamp = actual.SecurityStamp;
                            return expectedUser;
                        }
                    }
                });
            });
        }
        public async Task WhenRegisteringANewUserWithNoExampleWork_ItShouldAddTheUserToTheDatabase()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new RegisterUserDbStatement(this.userManager.Object, testDatabase, this.requestSnapshot);

                var hashedPassword = RegistrationData.Password + "1";
                this.passwordHasher.Setup(v => v.HashPassword(RegistrationData.Password.Value)).Returns(hashedPassword);

                await testDatabase.TakeSnapshotAsync();

                await this.target.ExecuteAsync(
                    UserId,
                    RegistrationData.Username,
                    RegistrationData.Email,
                    null,
                    RegistrationData.Password,
                    TimeStamp);

                var expectedUser = new FifthweekUser
                {
                    Id                  = UserId.Value,
                    UserName            = RegistrationData.Username.Value,
                    Email               = RegistrationData.Email.Value,
                    ExampleWork         = null,
                    RegistrationDate    = TimeStamp,
                    LastSignInDate      = SqlDateTime.MinValue.Value,
                    LastAccessTokenDate = SqlDateTime.MinValue.Value,
                    PasswordHash        = hashedPassword,
                };

                return(new ExpectedSideEffects
                {
                    Insert = new WildcardEntity <FifthweekUser>(expectedUser)
                    {
                        Expected = actual =>
                        {
                            expectedUser.SecurityStamp = actual.SecurityStamp;
                            return expectedUser;
                        }
                    }
                });
            });
        }