public async void ShouldThrowValidationExceptionOnCreateWhenCreatedDateIsNotRecentAndLogItAsync(
            int minutes)
        {
            // given
            DateTimeOffset randomDate        = GetRandomDateTime();
            Assignment     randomAssignment  = CreateRandomAssignment(randomDate);
            Assignment     invalidAssignment = randomAssignment;

            invalidAssignment.CreatedDate = randomDate.AddMinutes(minutes);
            invalidAssignment.UpdatedDate = invalidAssignment.CreatedDate;
            var invalidAssignmentException = new InvalidAssignmentException();

            invalidAssignmentException.AddData(
                key: nameof(Assignment.CreatedDate),
                values: $"Date is not recent");

            var expectedAssignmentValidationException =
                new AssignmentValidationException(invalidAssignmentException);

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

            // when
            ValueTask <Assignment> createAssignmentTask =
                this.assignmentService.CreateAssignmentAsync(invalidAssignment);

            // then
            await Assert.ThrowsAsync <AssignmentValidationException>(() =>
                                                                     createAssignmentTask.AsTask());

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

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

            this.storageBrokerMock.Verify(broker =>
                                          broker.InsertAssignmentAsync(It.IsAny <Assignment>()),
                                          Times.Never);

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
        }
        public async void ShouldThrowValidationExceptionOnCreateWhenUpdatedByIsNotSameToCreatedByAndLogItAsync()
        {
            // given
            DateTimeOffset dateTime          = GetRandomDateTime();
            Assignment     randomAssignment  = CreateRandomAssignment(dateTime);
            Assignment     invalidAssignment = randomAssignment;

            invalidAssignment.UpdatedBy = Guid.NewGuid();
            var invalidAssignmentInputException = new InvalidAssignmentException();

            invalidAssignmentInputException.AddData(
                key: nameof(Assignment.UpdatedBy),
                values: $"Id is not the same as {nameof(Assignment.CreatedBy)}");

            var expectedAssignmentValidationException =
                new AssignmentValidationException(invalidAssignmentInputException);

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

            // when
            ValueTask <Assignment> createAssignmentTask =
                this.assignmentService.CreateAssignmentAsync(invalidAssignment);

            // then
            await Assert.ThrowsAsync <AssignmentValidationException>(() =>
                                                                     createAssignmentTask.AsTask());

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

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

            this.storageBrokerMock.Verify(broker =>
                                          broker.InsertAssignmentAsync(It.IsAny <Assignment>()),
                                          Times.Never);

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
        }
        public async void ShouldThrowValidationExceptionOnModifyWhenUpdatedDateIsSameAsCreatedDateAndLogItAsync()
        {
            // given
            DateTimeOffset dateTime                   = GetRandomDateTime();
            Assignment     randomAssignment           = CreateRandomAssignment(dateTime);
            Assignment     invalidAssignment          = randomAssignment;
            var            invalidAssignmentException = new InvalidAssignmentException();

            invalidAssignmentException.AddData(
                key: nameof(Assignment.UpdatedDate),
                values: $"UpdatedDate is the same as {nameof(Assignment.CreatedDate)}");

            var expectedAssignmentValidationException =
                new AssignmentValidationException(invalidAssignmentException);

            // when
            ValueTask <Assignment> modifyAssignmentTask =
                this.assignmentService.ModifyAssignmentAsync(invalidAssignment);

            // then
            await Assert.ThrowsAsync <AssignmentValidationException>(() =>
                                                                     modifyAssignmentTask.AsTask());

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

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

            this.storageBrokerMock.Verify(broker =>
                                          broker.SelectAssignmentByIdAsync(It.IsAny <Guid>()),
                                          Times.Never);

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.loggingBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
        }
        public async Task ShouldThrowValidationExceptionOnModifyWhenAssignmentIsInvalidAndLogItAsync(
            string invalidText)
        {
            // given
            var invalidAssignment = new Assignment
            {
                Label   = invalidText,
                Content = invalidText
            };

            var invalidAssignmentException = new InvalidAssignmentException();

            invalidAssignmentException.AddData(
                key: nameof(Assignment.Id),
                values: "Id is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.Label),
                values: "Text is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.Content),
                values: "Text is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.Deadline),
                values: "Date is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.CreatedBy),
                values: "Id is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.UpdatedBy),
                values: "Id is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.CreatedDate),
                values: "Date is required");

            invalidAssignmentException.AddData(
                key: nameof(Assignment.UpdatedDate),
                values: "Date is required");

            var expectedAssignmentValidationException =
                new AssignmentValidationException(invalidAssignmentException);

            //when
            ValueTask <Assignment> modifyAssignmentTask =
                this.assignmentService.ModifyAssignmentAsync(invalidAssignment);

            //then
            await Assert.ThrowsAsync <AssignmentValidationException>(() =>
                                                                     modifyAssignmentTask.AsTask());

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

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

            this.dateTimeBrokerMock.VerifyNoOtherCalls();
            this.storageBrokerMock.VerifyNoOtherCalls();
            this.dateTimeBrokerMock.VerifyNoOtherCalls();
        }