public async Task ShouldThrowValidationExceptionOnRegisterIfStudentAlreadyExistsAndLogItAsync()
        {
            // given
            Student randomStudent                      = CreateRandomStudent();
            Student inputStudent                       = randomStudent;
            Student storageStudent                     = inputStudent;
            string  someMessage                        = new MnemonicString().GetValue();
            var     duplicateKeyException              = new DuplicateKeyException(someMessage);
            var     alreadyExistsStudentException      = new AlreadyExistsStudentException(duplicateKeyException);
            var     expectedStudentValidationException = new StudentValidationException(alreadyExistsStudentException);

            this.storageBrokerMock.Setup(broker =>
                                         broker.InsertStudentAsync(inputStudent))
            .ThrowsAsync(duplicateKeyException);

            // when
            ValueTask <Student> submitStudentTask =
                this.studentService.RegisterStudentAsync(inputStudent);

            // then
            await Assert.ThrowsAsync <StudentValidationException>(() => submitStudentTask.AsTask());

            this.storageBrokerMock.Verify(broker =>
                                          broker.InsertStudentAsync(inputStudent),
                                          Times.Once);

            this.loggingBrokerMock.Verify(broker =>
                                          broker.LogError(It.Is(SameExceptionAs(expectedStudentValidationException))),
                                          Times.Once);

            this.storageBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
        }
        private async ValueTask <Student> TryCatch(ReturningStudentFunction returningStudentFunction)
        {
            try
            {
                return(await returningStudentFunction());
            }
            catch (NullStudentException nullStudentException)
            {
                throw CreateAndLogValidationException(nullStudentException);
            }
            catch (InvalidStudentException invalidStudentException)
            {
                throw CreateAndLogValidationException(invalidStudentException);
            }
            catch (NotFoundStudentException nullStudentException)
            {
                throw CreateAndLogValidationException(nullStudentException);
            }
            catch (SqlException sqlException)
            {
                var failedStudentStorageException =
                    new FailedStudentStorageException(sqlException);

                throw CreateAndLogCriticalDependencyException(failedStudentStorageException);
            }
            catch (DuplicateKeyException duplicateKeyException)
            {
                var alreadyExistsStudentException =
                    new AlreadyExistsStudentException(duplicateKeyException);

                throw CreateAndLogDependencyValidationException(alreadyExistsStudentException);
            }
            catch (DbUpdateConcurrencyException dbUpdateConcurrencyException)
            {
                var lockedStudentException = new LockedStudentException(dbUpdateConcurrencyException);

                throw CreateAndLogDependencyException(lockedStudentException);
            }
            catch (DbUpdateException dbUpdateException)
            {
                var failedStudentStorageException =
                    new FailedStudentStorageException(dbUpdateException);

                throw CreateAndLogDependencyException(failedStudentStorageException);
            }
            catch (Exception exception)
            {
                var failedStudentServiceException =
                    new FailedStudentServiceException(exception);

                throw CreateAndLogServiceException(failedStudentServiceException);
            }
        }
        public async void ShouldThrowValidationExceptionOnRegisterWhenStudentAlreadyExistsAndLogItAsync()
        {
            // given
            DateTimeOffset dateTime             = GetRandomDateTime();
            Student        randomStudent        = CreateRandomStudent(dateTime);
            Student        alreadyExistsStudent = randomStudent;

            alreadyExistsStudent.UpdatedBy = alreadyExistsStudent.CreatedBy;
            string randomMessage         = GetRandomMessage();
            string exceptionMessage      = randomMessage;
            var    duplicateKeyException = new DuplicateKeyException(exceptionMessage);

            var alreadyExistsStudentException =
                new AlreadyExistsStudentException(duplicateKeyException);

            var expectedStudentValidationException =
                new StudentValidationException(alreadyExistsStudentException);

            this.dateTimeBrokerMock.Setup(broker =>
                                          broker.GetCurrentDateTime())
            .Returns(dateTime);

            this.storageBrokerMock.Setup(broker =>
                                         broker.InsertStudentAsync(alreadyExistsStudent))
            .ThrowsAsync(duplicateKeyException);

            // when
            ValueTask <Student> registerStudentTask =
                this.studentService.RegisterStudentAsync(alreadyExistsStudent);

            // then
            await Assert.ThrowsAsync <StudentValidationException>(() =>
                                                                  registerStudentTask.AsTask());

            this.dateTimeBrokerMock.Verify(broker =>
                                           broker.GetCurrentDateTime(),
                                           Times.Once);

            this.storageBrokerMock.Verify(broker =>
                                          broker.InsertStudentAsync(alreadyExistsStudent),
                                          Times.Once);

            this.loggingBrokerMock.Verify(broker =>
                                          broker.LogError(It.Is(SameExceptionAs(expectedStudentValidationException))),
                                          Times.Once);

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
        }
        public async Task ShouldThrowDependencyValidationExceptionOnRegisterWhenStudentAlreadyExistsAndLogItAsync()
        {
            // given
            Student someStudent = CreateRandomStudent();
            string  someMessage = GetRandomMessage();

            var duplicateKeyException =
                new DuplicateKeyException(someMessage);

            var alreadyExistsStudentException =
                new AlreadyExistsStudentException(duplicateKeyException);

            var expectedStudentDependencyValidationException =
                new StudentDependencyValidationException(alreadyExistsStudentException);

            this.dateTimeBrokerMock.Setup(broker =>
                                          broker.GetCurrentDateTime())
            .Throws(duplicateKeyException);

            // when
            ValueTask <Student> registerStudentTask =
                this.studentService.RegisterStudentAsync(someStudent);

            // then
            await Assert.ThrowsAsync <StudentDependencyValidationException>(() =>
                                                                            registerStudentTask.AsTask());

            this.dateTimeBrokerMock.Verify(broker =>
                                           broker.GetCurrentDateTime(),
                                           Times.Once);

            this.loggingBrokerMock.Verify(broker =>
                                          broker.LogError(It.Is(SameValidationExceptionAs(
                                                                    expectedStudentDependencyValidationException))),
                                          Times.Once);

            this.storageBrokerMock.Verify(broker =>
                                          broker.InsertStudentAsync(someStudent),
                                          Times.Never);

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
        }
        private async ValueTask <Student> TryCatch(ReturningStudentFunction returningStudentFunction)
        {
            try
            {
                return(await returningStudentFunction());
            }
            catch (NullStudentException nullStudentException)
            {
                throw CreateAndLogValidationException(nullStudentException);
            }
            catch (InvalidStudentException invalidStudentException)
            {
                throw CreateAndLogValidationException(invalidStudentException);
            }
            catch (SqlException sqlException)
            {
                throw CreateAndLogCriticalDependencyException(sqlException);
            }
            catch (NotFoundStudentException studentNotFoundException)
            {
                throw CreateAndLogValidationException(studentNotFoundException);
            }
            catch (DuplicateKeyException duplicateKeyException)
            {
                var studentAlreadyExistsException =
                    new AlreadyExistsStudentException(duplicateKeyException);

                throw CreateAndLogValidationException(studentAlreadyExistsException);
            }
            catch (DbUpdateException dbUpdateException)
            {
                throw CreateAndLogDependencyException(dbUpdateException);
            }
            catch (ValidationException validationException)
            {
                throw CreateAndLogValidationException(validationException);
            }
            catch (Exception exception)
            {
                throw CreateAndLogServiceException(exception);
            }
        }