public void given_a_request_with_null_properties_when_GetProcessImage_controller_method_is_called_then_it_makes_the_logger_display_those_null_properties_as_string_saying_null() //otherwise it would just display empty
        {
            //arrange
            var request = new GetProcessImageRequest(); // both properties are 'null' now.

            //need the validation failure here, because the implementation would only fire off upon validation failure.
            var validationErrorList = new List <ValidationFailure>();

            validationErrorList.Add(new ValidationFailure(_faker.Random.Word(), _faker.Random.Word()));

            var fakeValidationResult = new FV.ValidationResult(validationErrorList); //Need to create ValidationResult so that I could setup Validator mock to return it upon '.Validate()' call. Also this is the only place where it's possible to manipulate the validation result - You can only make the validation result invalid by inserting a list of validation errors as a parameter through a constructor. The boolean '.IsValid' comes from expression 'IsValid => Errors.Count == 0;', so it can't be set manually.

            _mockGetValidator.Setup(v => v.Validate(It.IsAny <GetProcessImageRequest>())).Returns(fakeValidationResult);

            string expectedLogMessageSubstring = $"Get ProcessImage request for Process Type: {"null"}, Process Reference: {"null"}, Image Id: {"null"} and File Extension: {"null"}"; //set up only substring, because the test only cares about this first part of the full log message that would be passed in.

            //act
            _processImageController.GetProcessImage(request);

            //assert
            _mockLogger.Verify(l => l.Log(
                                   LogLevel.Information,
                                   It.IsAny <EventId>(),
                                   It.Is <FormattedLogValues>(v => v.ToString().Contains(expectedLogMessageSubstring)),
                                   It.IsAny <Exception>(),
                                   It.IsAny <Func <object, Exception, string> >()
                                   ), Times.AtLeastOnce);
        }
        public GetProcessImageResponse ExecuteGet(GetProcessImageRequest request)
        {
            var imageKey        = ImagePersistingHelper.generateImageKey(request.processType, request.imageId, request.processRef, request.fileExtension);
            var gatewayResponse = _processImageGateway.RetrieveImage(imageKey);

            return(new GetProcessImageResponse(gatewayResponse, DateTime.Now, request));
        }
        public IActionResult GetProcessImage([FromRoute] GetProcessImageRequest requestData)
        {
            _logger.LogInformation($"Get ProcessImage request for Process Type: {requestData.processType ?? "null"}, Process Reference: {requestData.processRef ?? "null"}, Image Id: {requestData.imageId ?? "null"} and File Extension: {requestData.fileExtension ?? "null"}");
            var validationResult = _getValidator.Validate(requestData);

            if (validationResult.IsValid)
            {
                try
                {
                    var usecaseResponse = _processImageUseCase.ExecuteGet(requestData);
                    return(Ok(usecaseResponse));
                }
                catch (ImageNotFound ex)
                {
                    return(NotFound($"The image with ID = {requestData.imageId} has not been found."));

                    throw ex;
                }
                catch (Exception ex)
                {
                    return(StatusCode(500, "An error has occured while processing the request - " + ex.Message + " " + ex.InnerException));
                }
            }

            _logger.LogInformation($"Get ProcessImage request for Process Type: {requestData.processType ?? "null"}, Process Reference: {requestData.processRef ?? "null"}, Image Id: {requestData.imageId ?? "null"} and File Extension: {requestData.fileExtension ?? "null"} did not pass the validation:\n\n{validationResult.Errors.Select(e => $"Validation error for: '{e.PropertyName}', message: '{e.ErrorMessage}'.").Aggregate((acc, m) => acc + "\n" + m)}");
            return(BadRequest(validationResult.Errors));
        }
        public void given_successful_request_validation_when_GetProcessImage_controller_method_is_called_then_it_calls_usecase_with_correct_data_based_of_request()
        {
            //arrange
            GetProcessImageRequest request = MatProcessDataHelper.CreateGetProcessImageRequestObject();

            _mockGetValidator.Setup(x => x.Validate(It.IsAny <GetProcessImageRequest>())).Returns(new FV.ValidationResult()); //setup validator to return a no error validation result

            //act
            _processImageController.GetProcessImage(request);

            //assert
            _mockUsecase.Verify(u => u.ExecuteGet(It.Is <GetProcessImageRequest>(obj =>
                                                                                 obj.processRef == request.processRef &&
                                                                                 obj.imageId == request.imageId
                                                                                 )), Times.Once);
        }
        public void given_a_request_with_null_properties_when_GetProcessImage_controller_method_is_called_then_it_makes_the_logger_display_those_null_properties_as_string_saying_null_during_the_initial_logger_call_independent_of_the_validator_behaviour()  //Since there's no validator setup, it returns no validation result. If the Verify bit shows that logger was called under these conditions, then this shows that validation result has no influence on logger being called at least once, which is important if you want to register that request happened regardless of the validity of the request.
        {
            //arrange
            var    request            = new GetProcessImageRequest(); //request with null properties
            string expectedLogMessage = $"Get ProcessImage request for Process Type: {"null"}, Process Reference: {"null"}, Image Id: {"null"} and File Extension: {"null"}";

            //act
            try { _processImageController.GetProcessImage(request); } catch (Exception ex) { } //the empty try-catch is needed to ignore the exception being thrown due to absense of validation result returned later down the line. The idea is that logger is the first thing that is being called once request comes in.

            //assert
            _mockLogger.Verify(l => l.Log(
                                   LogLevel.Information,
                                   It.IsAny <EventId>(),
                                   It.Is <FormattedLogValues>(v => v.ToString().Contains(expectedLogMessage)),
                                   It.IsAny <Exception>(),
                                   It.IsAny <Func <object, Exception, string> >()
                                   ), Times.AtLeastOnce);
        }
        public void given_an_ImageNotFound_exception_thrown_by_gateway_verify_controller_returns_404_status_code_and_message()
        {
            var expectedStatusCode = 404;
            var request            = new GetProcessImageRequest()
            {
                imageId = _faker.Random.Guid().ToString()
            };                                                                                        //an empty request will be invalid

            var expectedErrorMessage = $"The image with ID = {request.imageId} has not been found.";

            var fakeValidationResult = new FV.ValidationResult();

            _mockGetValidator.Setup(v => v.Validate(It.IsAny <GetProcessImageRequest>())).Returns(fakeValidationResult);
            _mockUsecase.Setup(x => x.ExecuteGet(request)).Throws <ImageNotFound>();
            //act
            var controllerResponse = _processImageController.GetProcessImage(request);
            var result             = controllerResponse as NotFoundObjectResult;

            //assert
            Assert.NotNull(controllerResponse);
            Assert.NotNull(result);
            Assert.AreEqual(expectedStatusCode, result.StatusCode);
            Assert.AreEqual(expectedErrorMessage, result.Value);
        }