public void Test_Process_Returns_NoResult_If_ObjectAttributesNoteableType_Not_Supported()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                autoMock.Mock <IMockCanHandle>()
                .Setup(p => p.CanHandle(It.IsAny <string>()))
                .Returns(false);

                var processor = autoMock.Create <MockGitlabProcessor>();
                RequestProcessResult result = processor.Process(new JObject
                {
                    [GitlabKeys.ObjectKind]       = GitlabKeys.ObjectKindNote,
                    [GitlabKeys.ObjectAttributes] = new JObject {
                        [GitlabKeys.NoteableType] = "some-unsupported-type"
                    }
                });

                Assert.False(result.Success);
                Assert.True(result.NoResult);
                Assert.Null(result.Reason);

                autoMock.Mock <IMockCanHandle>()
                .Verify(p => p.CanHandle("some-unsupported-type"), Times.Once);
            }
        }
        public void Test_TryFormat_Returns_Positive_If_Message_Was_Formatted(string createdAt, string updatedAt, string expectedText)
        {
            using (AutoMock mock = AutoMock.GetLoose(this.output.Capture()))
            {
                var formatter = mock.Create <CommentSnippetMessageFormatter>();

                var request = new JObject
                {
                    [GitlabKeys.User] = new JObject {
                        [GitlabKeys.Name] = "A-User-Name"
                    },
                    [GitlabKeys.Project] = new JObject
                    {
                        [GitlabKeys.Name]   = "A-Project-Name",
                        [GitlabKeys.WebUrl] = "A-Web-Url"
                    },
                    [GitlabKeys.ObjectAttributes] = new JObject
                    {
                        [GitlabKeys.Note]      = "A-Note",
                        [GitlabKeys.Url]       = "A-Url",
                        [GitlabKeys.CreatedAt] = createdAt,
                        [GitlabKeys.UpdatedAt] = updatedAt
                    }
                };

                RequestProcessResult result = formatter.TryFormat(request, out string msg);
                Assert.True(result.Success);
                Assert.False(result.NoResult);
                Assert.Null(result.Reason);

                string expected = $"[A-Project-Name](A-Web-Url). *A-User-Name* has [{expectedText}](A-Url) on the code snippet!\r\n\r\nA-Note";
                Assert.Equal(expected, msg);
            }
        }
Пример #3
0
        public void Test_Process_Does_Not_Call_MessageClient_If_The_Message_Was_Not_Formatted()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                string mockFormatterResult;
                autoMock.Mock <IMergeRequestMessageFormatter>()
                .Setup(p => p.TryFormat(It.IsAny <JObject>(), out mockFormatterResult))
                .Returns(RequestProcessResult.CreateFailure("some-reason"));

                var processor = autoMock.Create <MergeRequestGitlabProcessor>();
                var request   = new JObject
                {
                    [GitlabKeys.ObjectKind] = GitlabKeys.ObjectKindMergeRequest
                };
                RequestProcessResult result = processor.Process(request);

                Assert.False(result.Success);
                Assert.False(result.NoResult);
                Assert.Equal("some-reason", result.Reason);

                autoMock.Mock <IMergeRequestMessageFormatter>()
                .Verify(p => p.TryFormat(request, out mockFormatterResult), Times.Once);

                autoMock.Mock <IMessageClient>()
                .Verify(p => p.ScheduleDelivery(It.IsAny <string>()), Times.Never);
            }
        }
Пример #4
0
        public void Test_Process_Calls_MessageClient_If_The_Message_Was_Formatted()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                string mockFormatterResult = "some-result";
                autoMock.Mock <IPipelineMessageFormatter>()
                .Setup(p => p.TryFormat(It.IsAny <JObject>(), out mockFormatterResult))
                .Returns(RequestProcessResult.CreateSuccess());

                var processor = autoMock.Create <PipelineFailureGitlabProcessor>();
                var request   = new JObject
                {
                    [GitlabKeys.ObjectKind]       = GitlabKeys.ObjectKindPipeline,
                    [GitlabKeys.ObjectAttributes] = new JObject {
                        [GitlabKeys.Status] = GitlabKeys.StatusFailed
                    }
                };
                RequestProcessResult result = processor.Process(request);

                Assert.True(result.Success);
                Assert.False(result.NoResult);
                Assert.Null(result.Reason);

                autoMock.Mock <IPipelineMessageFormatter>()
                .Verify(p => p.TryFormat(request, out mockFormatterResult), Times.Once);

                autoMock.Mock <IMessageClient>()
                .Verify(p => p.ScheduleDelivery(mockFormatterResult), Times.Once);
            }
        }
Пример #5
0
        public void Test_TryFormat_Returns_Negative_If_Request_Has_No_Required_Attributes()
        {
            using (AutoMock mock = AutoMock.GetLoose(this.output.Capture()))
            {
                var formatter = mock.Create <PipelineMessageFormatter>();

                RequestProcessResult result = formatter.TryFormat(new JObject(), out string _);
                Assert.False(result.Success);
                Assert.False(result.NoResult);
                string expected1 = $"1. The json object is missing the field: \"{GitlabKeys.Project}\"{Environment.NewLine}" +
                                   $"2. The json object is missing the field: \"{GitlabKeys.ObjectAttributes}\"{Environment.NewLine}" +
                                   $"3. The json object is missing the field: \"{GitlabKeys.Commit}\"";
                Assert.Equal(expected1, result.Reason);


                var request2 = new JObject {
                    [GitlabKeys.Project] = new JObject(), [GitlabKeys.ObjectAttributes] = new JObject(), [GitlabKeys.Commit] = new JObject()
                };
                result = formatter.TryFormat(request2, out string _);
                Assert.False(result.Success);
                Assert.False(result.NoResult);
                string expected2 = $"1. The json object is missing the field: \"{GitlabKeys.Project}.{GitlabKeys.Name}\"{Environment.NewLine}" +
                                   $"2. The json object is missing the field: \"{GitlabKeys.Project}.{GitlabKeys.WebUrl}\"{Environment.NewLine}" +
                                   $"3. The json object is missing the field: \"{GitlabKeys.Project}.{GitlabKeys.PathWithNamespace}\"{Environment.NewLine}" +
                                   $"4. The json object is missing the field: \"{GitlabKeys.ObjectAttributes}.{GitlabKeys.Ref}\"{Environment.NewLine}" +
                                   $"5. The json object is missing the field: \"{GitlabKeys.ObjectAttributes}.{GitlabKeys.Id}\"{Environment.NewLine}" +
                                   $"6. The json object is missing the field: \"{GitlabKeys.Commit}.{GitlabKeys.Id}\"{Environment.NewLine}" +
                                   $"7. The json object is missing the field: \"{GitlabKeys.Commit}.{GitlabKeys.Message}\"{Environment.NewLine}" +
                                   $"8. The json object is missing the field: \"{GitlabKeys.Commit}.{GitlabKeys.Url}\"{Environment.NewLine}" +
                                   $"9. The json object is missing the field: \"{GitlabKeys.Commit}.{GitlabKeys.Author}\"";
                Assert.Equal(expected2, result.Reason);
            }
        }
        public async Task <IActionResult> Hook()
        {
            IActionResult result;

            using (var reader = new StreamReader(this.Request.Body))
            {
                string json = await reader.ReadToEndAsync();

                if (this.logger.IsEnabled(LogLevel.Trace))
                {
                    this.logger.LogTrace(json);
                }

                this.logger.LogDebug("Parsing and processing the incoming request");
                JObject obj = JObject.Parse(json);
                RequestProcessResult processResult = this.gitlabProcessService.ProcessRequest(obj);

                this.logger.LogDebug("The processing result was: {0}", processResult);
                result = processResult.Success
                    ? (IActionResult)this.Ok()
                    : this.BadRequest(processResult.Reason);
            }

            return(result);
        }
        public void Test_ProcessRequest_Returns_The_First_Successful_Result()
        {
            var m1 = new Mock <IGitlabProcessor>();

            m1.Setup(p => p.Process(It.IsAny <JObject>()))
            .Returns(RequestProcessResult.CreateNoResult());  //no result
            var m2 = new Mock <IGitlabProcessor>();

            m2.Setup(p => p.Process(It.IsAny <JObject>()))
            .Returns(RequestProcessResult.CreateSuccess());  //success
            var m3 = new Mock <IGitlabProcessor>();

            m3.Setup(p => p.Process(It.IsAny <JObject>()))
            .Returns(RequestProcessResult.CreateNoResult());  //should not have been called

            using (AutoMock mock = AutoMock.GetLoose(builder =>
            {
                builder.RegisterXUnit(this.output);
                builder.RegisterInstance(m1.Object);
                builder.RegisterInstance(m2.Object);
                builder.RegisterInstance(m3.Object);
            }))
            {
                var service = mock.Create <GitlabProcessServiceImpl>();

                JObject request             = JObject.Parse("{prop:'value'}");
                RequestProcessResult result = service.ProcessRequest(request);

                Assert.True(result.Success);

                m1.Verify(p => p.Process(request), Times.Once);
                m2.Verify(p => p.Process(request), Times.Once);
                m3.Verify(p => p.Process(request), Times.Never);
            }
        }
        public RequestProcessResult Process(JObject request)
        {
            RequestProcessResult result;
            string objectKind = request[GitlabKeys.ObjectKind]?.ToString();

            this.logger.LogTrace("The request object kind was determined as: \"{0}\"", objectKind);

            if (string.Equals(objectKind, GitlabKeys.ObjectKindMergeRequest, StringComparison.InvariantCultureIgnoreCase))
            {
                result = this.formatter.TryFormat(request, out string message);
                if (result.Success)
                {
                    this.logger.LogDebug("Successfully formatted the message: \"{0}\"", message);
                    this.messageClient.ScheduleDelivery(message);
                }
                else
                {
                    this.logger.LogDebug("Could not format the message: {@0}", result);
                }
            }
            else
            {
                this.logger.LogTrace("Can not handle the request of the \"{0}\" object kind", objectKind);
                result = RequestProcessResult.CreateNoResult();
            }

            return(result);
        }
        public RequestProcessResult Process(JObject request)
        {
            RequestProcessResult result;

            string objectKind = request[GitlabKeys.ObjectKind]?.ToString();

            this.logger.LogTrace("The request object kind was determined as: \"{0}\"", objectKind);

            if (string.Equals(objectKind, GitlabKeys.ObjectKindNote, StringComparison.InvariantCultureIgnoreCase))
            {
                var errors = new JTokenErrors();

                string noteableType = request.RequireChild(GitlabKeys.ObjectAttributes, errors)?.RequireString(GitlabKeys.NoteableType, errors);
                this.logger.LogDebug("The noteable type was determined as \"{0}\"", noteableType);

                if (errors.HasAny)
                {
                    string error = errors.Compose();
                    result = RequestProcessResult.CreateFailure(error);
                    this.logger.LogDebug("The request processing was rejected with message: \"{0}\"", error);
                }
                else
                {
                    if (this.CanHandle(noteableType))
                    {
                        result = this.TryFormat(request, out string message);
                        if (result.Success)
                        {
                            this.logger.LogDebug("Successfully formatted the message: \"{0}\"", message);
                            this.messageClient.ScheduleDelivery(message);
                        }
                        else
                        {
                            this.logger.LogDebug("Could not format the message: {@0}", result);
                        }
                    }
                    else
                    {
                        this.logger.LogDebug("Can not handle the request with the \"{0}\" noteable type", noteableType);
                        result = RequestProcessResult.CreateNoResult();
                    }
                }
            }
            else
            {
                this.logger.LogTrace("Can not handle the request of the \"{0}\" object kind", objectKind);
                result = RequestProcessResult.CreateNoResult();
            }

            return(result);
        }
Пример #10
0
        public void Test_Process_Returns_NoResult_If_ObjectKind_Not_Supported()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                var processor = autoMock.Create <PipelineFailureGitlabProcessor>();
                RequestProcessResult result = processor.Process(new JObject {
                    [GitlabKeys.ObjectKind] = "some-unknown-kind"
                });

                Assert.False(result.Success);
                Assert.True(result.NoResult);
                Assert.Null(result.Reason);
            }
        }
Пример #11
0
        public void Test_Process_Returns_Failure_If_ObjectAttributes_Missing()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                var processor = autoMock.Create <PipelineFailureGitlabProcessor>();
                RequestProcessResult result = processor.Process(new JObject {
                    [GitlabKeys.ObjectKind] = GitlabKeys.ObjectKindPipeline
                });

                Assert.False(result.Success);
                Assert.False(result.NoResult);
                string expected = $"1. The json object is missing the field: \"{GitlabKeys.ObjectAttributes}\"";
                Assert.Equal(expected, result.Reason);
            }
        }
Пример #12
0
        public RequestProcessResult TryFormat(JObject request, out string message)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var errors = new JTokenErrors();

            JToken authorNode     = request.RequireChild(GitlabKeys.User, errors);
            JToken assigneeNode   = request.RequireChild(GitlabKeys.Assignee, errors);
            JToken projectNode    = request.RequireChild(GitlabKeys.Project, errors);
            JToken attributesNode = request.RequireChild(GitlabKeys.ObjectAttributes, errors);

            UserInfo    author      = UserInfo.TryRead(authorNode, errors);
            UserInfo    assignee    = UserInfo.TryRead(assigneeNode, errors);
            ProjectInfo projectInfo = ProjectInfo.TryRead(projectNode, errors);

            string sourceBranch = attributesNode?.RequireString(GitlabKeys.SourceBranch, errors);
            string targetBranch = attributesNode?.RequireString(GitlabKeys.TargetBranch, errors);
            string state        = attributesNode?.RequireString(GitlabKeys.State, errors);
            string title        = attributesNode?.RequireString(GitlabKeys.Title, errors);
            string url          = attributesNode?.RequireString(GitlabKeys.Url, errors);
            string iid          = attributesNode?.RequireString(GitlabKeys.Iid, errors);
            string createdAt    = attributesNode?[GitlabKeys.CreatedAt]?.ToString();
            string updatedAt    = attributesNode?[GitlabKeys.UpdatedAt]?.ToString();

            RequestProcessResult result;

            if (errors.HasAny)
            {
                string error = errors.Compose();
                this.logger.LogDebug("The request processing was rejected with error: \"{0}\"", error);

                message = null;
                result  = RequestProcessResult.CreateFailure(error);
            }
            else
            {
                state   = MergeRequestMessageFormatter.GetMergeRequestState(state, createdAt, updatedAt);
                message = $"[{projectInfo.Name}]({projectInfo.Url}). The merge request [#{iid} {title}]({url}) (branch [{sourceBranch}]({projectInfo.Url}/tree/{sourceBranch}) to [{targetBranch}]({projectInfo.Url}/tree/{targetBranch})) was {state} by [{author.Name}]({projectInfo.Server}{author.UserName}).\r\nAssignee [{assignee.Name}]({projectInfo.Server}{assignee.UserName}).";
                this.logger.LogTrace("Composed the message: \"{0}\"", message);
                result = RequestProcessResult.CreateSuccess();
            }

            return(result);
        }
        public void Test_ProcessRequest_Returns_Failure_If_No_Success_Result_Received()
        {
            using (AutoMock mock = AutoMock.GetLoose(this.output.Capture()))
            {
                mock.Mock <IGitlabProcessor>()
                .Setup(p => p.Process(It.IsAny <JObject>()))
                .Returns(RequestProcessResult.CreateNoResult());

                var service = mock.Create <GitlabProcessServiceImpl>();

                JObject request             = JObject.Parse("{prop:'value'}");
                RequestProcessResult result = service.ProcessRequest(request);

                Assert.False(result.Success);
                Assert.Equal("The system is not capable of processing such requests", result.Reason);
            }
        }
        public RequestProcessResult TryFormat(JObject request, out string message)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var errors = new JTokenErrors();

            JToken author       = request.RequireChild(GitlabKeys.User, errors);
            JToken project      = request.RequireChild(GitlabKeys.Project, errors);
            JToken attributes   = request.RequireChild(GitlabKeys.ObjectAttributes, errors);
            JToken mergeRequest = request.RequireChild(GitlabKeys.MergeRequest, errors);

            string authorName  = author?.RequireString(GitlabKeys.Name, errors);
            string projectName = project?.RequireString(GitlabKeys.Name, errors);
            string projectUrl  = project?.RequireString(GitlabKeys.WebUrl, errors);

            string snippetText = attributes?.RequireString(GitlabKeys.Note, errors);
            string snippetUrl  = attributes?.RequireString(GitlabKeys.Url, errors);
            string createdAt   = attributes?[GitlabKeys.CreatedAt]?.ToString();
            string updatedAt   = attributes?[GitlabKeys.UpdatedAt]?.ToString();

            string mrTitle = mergeRequest?.RequireString(GitlabKeys.Title, errors);
            string mrIid   = mergeRequest?.RequireString(GitlabKeys.Iid, errors);

            RequestProcessResult result;

            if (errors.HasAny)
            {
                string error = errors.Compose();
                this.logger.LogDebug("The request processing was rejected with error: \"{0}\"", error);

                message = null;
                result  = RequestProcessResult.CreateFailure(error);
            }
            else
            {
                string commentAction = CommentRequestMessageFormatter.GetCommentAction(createdAt, updatedAt);
                message = $"[{projectName}]({projectUrl}). *{authorName}* has [{commentAction}]({snippetUrl}) on the MR [#{mrIid} {mrTitle}]({projectUrl}/merge_requests/{mrIid})!\r\n\r\n{snippetText}";
                this.logger.LogTrace("Composed the message: \"{0}\"", message);
                result = RequestProcessResult.CreateSuccess();
            }

            return(result);
        }
Пример #15
0
        public void Test_TryFormat_Returns_Positive_If_Message_Was_Formatted(string state, string createdAt, string updatedAt, string expectedText)
        {
            using (AutoMock mock = AutoMock.GetLoose(this.output.Capture()))
            {
                var formatter = mock.Create <MergeRequestMessageFormatter>();

                var request = new JObject
                {
                    [GitlabKeys.User] = new JObject
                    {
                        [GitlabKeys.Name]     = "A-User",
                        [GitlabKeys.UserName] = "A-User-Name"
                    },
                    [GitlabKeys.Assignee] = new JObject
                    {
                        [GitlabKeys.Name]     = "An-Assignee",
                        [GitlabKeys.UserName] = "An-Assignee-Name"
                    },
                    [GitlabKeys.Project] = new JObject
                    {
                        [GitlabKeys.Name]              = "A-Project-Name",
                        [GitlabKeys.WebUrl]            = "A-Web-Url/namespace",
                        [GitlabKeys.PathWithNamespace] = "namespace"
                    },
                    [GitlabKeys.ObjectAttributes] = new JObject
                    {
                        [GitlabKeys.SourceBranch] = "A-Source-Branch",
                        [GitlabKeys.TargetBranch] = "A-Target-Branch",
                        [GitlabKeys.State]        = state,
                        [GitlabKeys.Title]        = "A-Title",
                        [GitlabKeys.Url]          = "A-Url",
                        [GitlabKeys.Iid]          = "A-Iid",
                        [GitlabKeys.CreatedAt]    = createdAt,
                        [GitlabKeys.UpdatedAt]    = updatedAt
                    }
                };

                RequestProcessResult result = formatter.TryFormat(request, out string msg);
                Assert.True(result.Success);
                Assert.False(result.NoResult);
                Assert.Null(result.Reason);

                string expected = $"[A-Project-Name](A-Web-Url/namespace). The merge request [#A-Iid A-Title](A-Url) (branch [A-Source-Branch](A-Web-Url/namespace/tree/A-Source-Branch) to [A-Target-Branch](A-Web-Url/namespace/tree/A-Target-Branch)) was {expectedText} by [A-User](A-Web-Url/A-User-Name).\r\nAssignee [An-Assignee](A-Web-Url/An-Assignee-Name).";
                Assert.Equal(expected, msg);
            }
        }
Пример #16
0
        public void Test_TryFormat_Returns_Positive_If_Message_Was_Formatted()
        {
            using (AutoMock mock = AutoMock.GetLoose(this.output.Capture()))
            {
                var formatter = mock.Create <PipelineMessageFormatter>();

                var request = new JObject
                {
                    [GitlabKeys.Project] = new JObject
                    {
                        [GitlabKeys.Name]              = "A-Project-Name",
                        [GitlabKeys.WebUrl]            = "A-Web-Url/Group/Project",
                        [GitlabKeys.PathWithNamespace] = "/Group/Project"
                    },
                    [GitlabKeys.ObjectAttributes] = new JObject
                    {
                        [GitlabKeys.Ref] = "A-Ref",
                        [GitlabKeys.Id]  = "A-Id"
                    },
                    [GitlabKeys.Commit] = new JObject
                    {
                        [GitlabKeys.Id]      = "us8dii909989ac978ac6a8w5ca8",
                        [GitlabKeys.Message] = "A-Commit-Message",
                        [GitlabKeys.Url]     = "A-Commit-Url",
                        [GitlabKeys.Author]  = new JObject
                        {
                            [GitlabKeys.Name]  = "A-Commit-Author",
                            [GitlabKeys.Email] = "A-Commit-Email"
                        }
                    }
                };

                RequestProcessResult result = formatter.TryFormat(request, out string msg);
                Assert.True(result.Success);
                Assert.False(result.NoResult);
                Assert.Null(result.Reason);

                const string expected = "[A-Project-Name](A-Web-Url/Group/Project). The pipeline [A-Id](A-Web-Url/Group/Project/pipelines/A-Id) has failed for the branch [A-Ref](A-Web-Url/Group/Project/tree/A-Ref)!" +
                                        "\r\n\r\nThe last commit [us8dii9](A-Commit-Url) by *A-Commit-Author*\r\nA-Commit-Message";
                Assert.Equal(expected, msg);
            }
        }
Пример #17
0
        public RequestProcessResult TryFormat(JObject request, out string message)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var errors = new JTokenErrors();

            JToken projectNode    = request.RequireChild(GitlabKeys.Project, errors);
            JToken attributesNode = request.RequireChild(GitlabKeys.ObjectAttributes, errors);
            JToken commitNode     = request.RequireChild(GitlabKeys.Commit, errors);

            ProjectInfo project    = ProjectInfo.TryRead(projectNode, errors);
            string      branchName = attributesNode?.RequireString(GitlabKeys.Ref, errors);
            string      pipelineId = attributesNode?.RequireString(GitlabKeys.Id, errors);
            CommitInfo  commit     = CommitInfo.TryRead(commitNode, errors);

            RequestProcessResult result;

            if (errors.HasAny)
            {
                string error = errors.Compose();
                this.logger.LogDebug("The request processing was rejected with error: \"{0}\"", error);

                message = null;
                result  = RequestProcessResult.CreateFailure(error);
            }
            else
            {
                message = $"[{project.Name}]({project.Url}). The pipeline [{pipelineId}]({project.Url}/pipelines/{pipelineId}) has failed for the branch [{branchName}]({project.Url}/tree/{branchName})!\r\n\r\n"
                          + $"The last commit [{commit.Hash}]({commit.Url}) by *{commit.AuthorName}*\r\n{commit.Message}";

                this.logger.LogTrace("Composed the message: \"{0}\"", message);
                result = RequestProcessResult.CreateSuccess();
            }

            return(result);
        }
        public void Test_Process_Calls_MessageClient_If_The_Message_Was_Formatted()
        {
            using (AutoMock autoMock = AutoMock.GetLoose(this.output.Capture()))
            {
                autoMock.Mock <IMockCanHandle>()
                .Setup(p => p.CanHandle(It.IsAny <string>()))
                .Returns(true);

                string mockFormatterResult = "some-result";
                autoMock.Mock <IMockFormatter>()
                .Setup(p => p.TryFormat(It.IsAny <JObject>(), out mockFormatterResult))
                .Returns(RequestProcessResult.CreateSuccess());

                var processor = autoMock.Create <MockGitlabProcessor>();
                var request   = new JObject
                {
                    [GitlabKeys.ObjectKind]       = GitlabKeys.ObjectKindNote,
                    [GitlabKeys.ObjectAttributes] = new JObject {
                        [GitlabKeys.NoteableType] = GitlabKeys.NoteableTypeSnippet
                    }
                };
                RequestProcessResult result = processor.Process(request);

                Assert.True(result.Success);
                Assert.False(result.NoResult);
                Assert.Null(result.Reason);

                autoMock.Mock <IMockCanHandle>()
                .Verify(p => p.CanHandle(GitlabKeys.NoteableTypeSnippet), Times.Once);

                autoMock.Mock <IMockFormatter>()
                .Verify(p => p.TryFormat(request, out mockFormatterResult), Times.Once);

                autoMock.Mock <IMessageClient>()
                .Verify(p => p.ScheduleDelivery(mockFormatterResult), Times.Once);
            }
        }
        protected override RequestProcessResult TryFormat(JObject request, out string message)
        {
            RequestProcessResult result = this.formatter.TryFormat(request, out message);

            return(result);
        }