From ade9824b4f8448e3cef9bab1a92a6ae64f418394 Mon Sep 17 00:00:00 2001 From: Haubold Date: Fri, 21 Oct 2022 18:24:48 +0200 Subject: [PATCH 1/2] executor should publosh if endWorkflow is set to dertine end of workflow;added test to assure behavior --- src/WorkflowCore/Services/WorkflowExecutor.cs | 6 ++ .../Services/WorkflowExecutorFixture.cs | 65 ++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 145f02d41..5163ac4ba 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -221,6 +221,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if (workflow.Status == WorkflowStatus.Complete) { + PublishWorkflowCompleted(workflow); return; } @@ -265,6 +266,11 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo await middlewareRunner.RunPostMiddleware(workflow, def); } + PublishWorkflowCompleted(workflow); + } + + private void PublishWorkflowCompleted(WorkflowInstance workflow) + { _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index e548b8e88..7180a0528 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -9,6 +9,9 @@ using WorkflowCore.Models; using WorkflowCore.Services; using Xunit; +using WorkflowCore.Models.LifeCycleEvents; +using Moq; +using Times = Moq.Times; namespace WorkflowCore.UnitTests.Services { @@ -19,7 +22,7 @@ public class WorkflowExecutorFixture protected IPersistenceProvider PersistenceProvider; protected IWorkflowRegistry Registry; protected IExecutionResultProcessor ResultProcesser; - protected ILifeCycleEventPublisher EventHub; + protected Mock EventHub; protected ICancellationProcessor CancellationProcessor; protected IServiceProvider ServiceProvider; protected IScopeProvider ScopeProvider; @@ -36,7 +39,7 @@ public WorkflowExecutorFixture() ScopeProvider = A.Fake(); Registry = A.Fake(); ResultProcesser = A.Fake(); - EventHub = A.Fake(); + EventHub = new Mock(); CancellationProcessor = A.Fake(); DateTimeProvider = A.Fake(); MiddlewareRunner = A.Fake(); @@ -82,7 +85,7 @@ public WorkflowExecutorFixture() var loggerFactory = new LoggerFactory(); //loggerFactory.AddConsole(LogLevel.Debug); - Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, loggerFactory); + Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub.Object, CancellationProcessor, Options, loggerFactory); } [Fact(DisplayName = "Should execute active step")] @@ -403,6 +406,62 @@ public void should_process_cancellations() A.CallTo(() => CancellationProcessor.ProcessCancellations(instance, A.Ignored, A.Ignored)).MustHaveHappened(); } + [Fact(DisplayName = "Should execute active step")] + public void should_execute_publisher_sends_Event_when_completed() + { + //arrange + var param = A.Fake(); + + var step1Body = A.Fake(); + A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); + WorkflowStep step1 = BuildFakeEndStep(step1Body, new List + { + param + }, + new List()); + + Given1StepWorkflow(step1, "Workflow", 1); + + var instance = new WorkflowInstance + { + WorkflowDefinitionId = "Workflow", + Version = 1, + Status = WorkflowStatus.Runnable, + NextExecution = 0, + Id = "001", + ExecutionPointers = new ExecutionPointerCollection(new List + { + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } + }) + }; + + EventHub.Setup(m => m.PublishNotification(new WorkflowCompleted())); + + //act + Subject.Execute(instance); + + //assert + EventHub.Verify(hub => hub.PublishNotification(It.IsAny()), Times.Once()); + A.CallTo(() => step1Body.RunAsync(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => ResultProcesser.ProcessExecutionResult(instance, A.Ignored, A.Ignored, step1, A.Ignored, A.Ignored)).MustNotHaveHappened(); + } + + private WorkflowStep BuildFakeEndStep(IStepBody stepBody, List inputs, List outputs) + { + var result = A.Fake(); + A.CallTo(() => result.Id).Returns(0); + A.CallTo(() => result.BodyType).Returns(stepBody.GetType()); + A.CallTo(() => result.ResumeChildrenAfterCompensation).Returns(true); + A.CallTo(() => result.RevertChildrenAfterCompensation).Returns(false); + A.CallTo(() => result.ConstructBody(ServiceProvider)).Returns(stepBody); + A.CallTo(() => result.Inputs).Returns(inputs); + A.CallTo(() => result.Outputs).Returns(outputs); + A.CallTo(() => result.Outcomes).Returns(new List()); + A.CallTo(() => result.InitForExecution(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).Returns(ExecutionPipelineDirective.EndWorkflow); + A.CallTo(() => result.BeforeExecute(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).Returns(ExecutionPipelineDirective.Next); + return result; + } + private void Given1StepWorkflow(WorkflowStep step1, string id, int version) { From 4729fb17bfb0ad6257caa33c0d9ad99c9a6d2950 Mon Sep 17 00:00:00 2001 From: Martin Dennhardt Date: Sat, 12 Aug 2023 16:02:47 +0000 Subject: [PATCH 2/2] clean up unit test --- .../Services/WorkflowExecutorFixture.cs | 49 +++++-------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index 7180a0528..9bd305f52 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -7,11 +7,9 @@ using FluentAssertions; using WorkflowCore.Interface; using WorkflowCore.Models; +using WorkflowCore.Models.LifeCycleEvents; using WorkflowCore.Services; using Xunit; -using WorkflowCore.Models.LifeCycleEvents; -using Moq; -using Times = Moq.Times; namespace WorkflowCore.UnitTests.Services { @@ -22,7 +20,7 @@ public class WorkflowExecutorFixture protected IPersistenceProvider PersistenceProvider; protected IWorkflowRegistry Registry; protected IExecutionResultProcessor ResultProcesser; - protected Mock EventHub; + protected ILifeCycleEventPublisher EventHub; protected ICancellationProcessor CancellationProcessor; protected IServiceProvider ServiceProvider; protected IScopeProvider ScopeProvider; @@ -39,7 +37,7 @@ public WorkflowExecutorFixture() ScopeProvider = A.Fake(); Registry = A.Fake(); ResultProcesser = A.Fake(); - EventHub = new Mock(); + EventHub = A.Fake(); CancellationProcessor = A.Fake(); DateTimeProvider = A.Fake(); MiddlewareRunner = A.Fake(); @@ -85,7 +83,7 @@ public WorkflowExecutorFixture() var loggerFactory = new LoggerFactory(); //loggerFactory.AddConsole(LogLevel.Debug); - Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub.Object, CancellationProcessor, Options, loggerFactory); + Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, loggerFactory); } [Fact(DisplayName = "Should execute active step")] @@ -406,19 +404,17 @@ public void should_process_cancellations() A.CallTo(() => CancellationProcessor.ProcessCancellations(instance, A.Ignored, A.Ignored)).MustHaveHappened(); } - [Fact(DisplayName = "Should execute active step")] - public void should_execute_publisher_sends_Event_when_completed() + [Fact(DisplayName = "Should send notification when workflow completes")] + public void should_send_notification_when_workflow_completes() { //arrange var param = A.Fake(); - var step1Body = A.Fake(); - A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); - WorkflowStep step1 = BuildFakeEndStep(step1Body, new List - { - param - }, - new List()); + // build a fake EndStep + WorkflowStep step1 = A.Fake(); + A.CallTo(() => step1.InitForExecution(A.Ignored, A.Ignored, + A.Ignored, A.Ignored)) + .Returns(ExecutionPipelineDirective.EndWorkflow); Given1StepWorkflow(step1, "Workflow", 1); @@ -435,34 +431,13 @@ public void should_execute_publisher_sends_Event_when_completed() }) }; - EventHub.Setup(m => m.PublishNotification(new WorkflowCompleted())); - //act Subject.Execute(instance); //assert - EventHub.Verify(hub => hub.PublishNotification(It.IsAny()), Times.Once()); - A.CallTo(() => step1Body.RunAsync(A.Ignored)).MustNotHaveHappened(); - A.CallTo(() => ResultProcesser.ProcessExecutionResult(instance, A.Ignored, A.Ignored, step1, A.Ignored, A.Ignored)).MustNotHaveHappened(); - } - - private WorkflowStep BuildFakeEndStep(IStepBody stepBody, List inputs, List outputs) - { - var result = A.Fake(); - A.CallTo(() => result.Id).Returns(0); - A.CallTo(() => result.BodyType).Returns(stepBody.GetType()); - A.CallTo(() => result.ResumeChildrenAfterCompensation).Returns(true); - A.CallTo(() => result.RevertChildrenAfterCompensation).Returns(false); - A.CallTo(() => result.ConstructBody(ServiceProvider)).Returns(stepBody); - A.CallTo(() => result.Inputs).Returns(inputs); - A.CallTo(() => result.Outputs).Returns(outputs); - A.CallTo(() => result.Outcomes).Returns(new List()); - A.CallTo(() => result.InitForExecution(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).Returns(ExecutionPipelineDirective.EndWorkflow); - A.CallTo(() => result.BeforeExecute(A.Ignored, A.Ignored, A.Ignored, A.Ignored)).Returns(ExecutionPipelineDirective.Next); - return result; + A.CallTo(() => EventHub.PublishNotification(A.Ignored)).MustHaveHappenedOnceExactly(); } - private void Given1StepWorkflow(WorkflowStep step1, string id, int version) { A.CallTo(() => Registry.GetDefinition(id, version)).Returns(new WorkflowDefinition