public async Task ShouldReceiveResponseAsExpected() { // given var expectedResponse = new CreateWorkflowInstanceWithResultResponse { BpmnProcessId = "process", Version = 1, WorkflowKey = 2, WorkflowInstanceKey = 121, Variables = "{\"foo\":\"bar\"}", }; TestService.AddRequestHandler(typeof(CreateWorkflowInstanceWithResultRequest), request => expectedResponse); // when var workflowInstanceResponse = await ZeebeClient.NewCreateWorkflowInstanceCommand() .BpmnProcessId("process") .LatestVersion() .WithResult() .Send(); // then Assert.AreEqual(2, workflowInstanceResponse.WorkflowKey); Assert.AreEqual(1, workflowInstanceResponse.Version); Assert.AreEqual(121, workflowInstanceResponse.WorkflowInstanceKey); Assert.AreEqual("process", workflowInstanceResponse.BpmnProcessId); Assert.AreEqual("{\"foo\":\"bar\"}", workflowInstanceResponse.Variables); }
public async Task ShouldRetrySendRequestOnUnavailableUntilSucceed() { // given var countdownEvent = new CountdownEvent(5); TestService.AddRequestHandler( typeof(CancelProcessInstanceRequest), req => { countdownEvent.Signal(); throw new RpcException(new Status(StatusCode.Unavailable, "exhausted")); }); var expectedRequest = new CancelProcessInstanceRequest { ProcessInstanceKey = 12113 }; // when var resultTask = ZeebeClient.NewCancelInstanceCommand(12113).SendWithRetry(); countdownEvent.Wait(TimeSpan.FromSeconds(10)); // then Assert.AreEqual(0, countdownEvent.CurrentCount); TestService.AddRequestHandler(typeof(CancelProcessInstanceRequest), req => new CancelProcessInstanceResponse()); await resultTask; var request = TestService.Requests[typeof(CancelProcessInstanceRequest)][0]; Assert.AreEqual(expectedRequest, request); var requestCount = TestService.Requests[typeof(CancelProcessInstanceRequest)].Count; Assert.GreaterOrEqual(requestCount, 5); }
public async Task ShouldSendDeployResourceAndGetResponseAsExpected() { // given var expectedResponse = new DeployWorkflowResponse { Key = 1 }; expectedResponse.Workflows.Add(new WorkflowMetadata { BpmnProcessId = "process", ResourceName = _demoProcessPath, Version = 1, WorkflowKey = 2 }); TestService.AddRequestHandler(typeof(DeployWorkflowRequest), request => expectedResponse); // when var deployWorkflowResponse = await ZeebeClient.NewDeployCommand() .AddResourceFile(_demoProcessPath) .Send(); // then Assert.AreEqual(1, deployWorkflowResponse.Key); Assert.AreEqual(1, deployWorkflowResponse.Workflows.Count); var workflowMetadata = deployWorkflowResponse.Workflows[0]; Assert.AreEqual("process", workflowMetadata.BpmnProcessId); Assert.AreEqual(1, workflowMetadata.Version); Assert.AreEqual(_demoProcessPath, workflowMetadata.ResourceName); Assert.AreEqual(2, workflowMetadata.WorkflowKey); }
public async Task shouldReceiveResponseAsExpected() { // given var expectedResponse = new GetWorkflowResponse { BpmnProcessId = "process", Version = 1, WorkflowKey = 2, ResourceName = DemoProcessPath, BpmnXml = File.ReadAllText(DemoProcessPath) }; TestService.AddRequestHandler(typeof(GetWorkflowRequest), request => expectedResponse); // when var workflowResourceResponse = await ZeebeClient.NewWorkflowResourceRequest() .BpmnProcessId("process") .LatestVersion() .Send(); // then Assert.AreEqual(2, workflowResourceResponse.WorkflowKey); Assert.AreEqual(1, workflowResourceResponse.Version); Assert.AreEqual(DemoProcessPath, workflowResourceResponse.ResourceName); Assert.AreEqual("process", workflowResourceResponse.BpmnProcessId); Assert.AreEqual(File.ReadAllText(DemoProcessPath), workflowResourceResponse.BpmnXml); }
public async Task ShouldReceiveResponseAsExpected() { // given var expectedResponse = new CreateProcessInstanceResponse { BpmnProcessId = "process", Version = 1, ProcessDefinitionKey = 2, ProcessInstanceKey = 121 }; TestService.AddRequestHandler(typeof(CreateProcessInstanceRequest), request => expectedResponse); // when var processInstanceResponse = await ZeebeClient.NewCreateProcessInstanceCommand() .BpmnProcessId("process") .LatestVersion() .Send(); // then Assert.AreEqual(2, processInstanceResponse.ProcessDefinitionKey); Assert.AreEqual(1, processInstanceResponse.Version); Assert.AreEqual(121, processInstanceResponse.ProcessInstanceKey); Assert.AreEqual("process", processInstanceResponse.BpmnProcessId); }
public async Task ShouldRetrySendRequestOnUnavailableUntilSucceed <TReq, TRes, TClientResponse>( TReq expectedRequest, TRes response, RequestCreator <TClientResponse> requestCreator) where TRes : IMessage { // given var countdownEvent = new CountdownEvent(5); TestService.AddRequestHandler( typeof(TReq), req => { countdownEvent.Signal(); throw new RpcException(new Status(StatusCode.Unavailable, "exhausted")); }); // when var resultTask = requestCreator(ZeebeClient).SendWithRetry(); countdownEvent.Wait(TimeSpan.FromSeconds(10)); // then Assert.AreEqual(0, countdownEvent.CurrentCount); TestService.AddRequestHandler(typeof(TReq), req => response); await resultTask; var request = TestService.Requests[typeof(TReq)][0]; Assert.AreEqual(expectedRequest, request); var requestCount = TestService.Requests[typeof(TReq)].Count; Assert.GreaterOrEqual(requestCount, 5); }
public async Task ShouldSendRequestReceiveResponseAsExpected() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 10_000L, MaxJobsToActivate = 1, Type = "foo", Worker = "jobWorker", }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var response = await ZeebeClient.NewActivateJobsCommand() .JobType("foo") .MaxJobsToActivate(1) .Timeout(TimeSpan.FromSeconds(10)) .WorkerName("jobWorker") .Send(); // then var actualRequest = TestService.Requests[0]; Assert.AreEqual(expectedRequest, actualRequest); var receivedJobs = response.Jobs; Assert.AreEqual(receivedJobs.Count, 3); AssertJob(receivedJobs[0], 1); AssertJob(receivedJobs[1], 2); AssertJob(receivedJobs[2], 3); }
public void ShouldSendCompleteInHandler() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 123_000L, MaxJobsToActivate = 3, Type = "foo", Worker = "jobWorker", RequestTimeout = 5_000L }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var signal = new EventWaitHandle(false, EventResetMode.AutoReset); var completedJobs = new List <IJob>(); using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { jobClient.NewCompleteJobCommand(job).Send(); completedJobs.Add(job); if (completedJobs.Count == 3) { signal.Set(); } }) .MaxJobsActive(3) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(123L)) .PollInterval(TimeSpan.FromMilliseconds(100)) .PollingTimeout(TimeSpan.FromSeconds(5L)) .Open()) { Assert.True(jobWorker.IsOpen()); signal.WaitOne(); } // then var actualActivateRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualActivateRequest); var completeRequests = TestService.Requests[typeof(CompleteJobRequest)]; while (completeRequests.Count != 3) { // busy loop to await 3 requests completeRequests = TestService.Requests[typeof(CompleteJobRequest)]; } Assert.GreaterOrEqual(completeRequests.Count, 3); Assert.GreaterOrEqual(completedJobs.Count, 3); AssertJob(completedJobs[0], 1); AssertJob(completedJobs[1], 2); AssertJob(completedJobs[2], 3); }
public void ShouldSendRequestsWithDifferentAmounts() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 123_000L, MaxJobsToActivate = 4, Type = "foo", Worker = "jobWorker", RequestTimeout = 5_000L }; var expectedSecondRequest = new ActivateJobsRequest { Timeout = 123_000L, MaxJobsToActivate = 2, // first response contains 3 jobs and one is handled (blocking) so 2 jobs remain in queue // so we can try to activate 2 new jobs Type = "foo", Worker = "jobWorker", RequestTimeout = 5_000L }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var receivedJobs = new List <IJob>(); using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { // block job handling using (var signal = new EventWaitHandle(false, EventResetMode.AutoReset)) { signal.WaitOne(); } }) .MaxJobsActive(4) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(123L)) .PollInterval(TimeSpan.FromMilliseconds(100)) .PollingTimeout(TimeSpan.FromMilliseconds(5_000L)) .Open()) { Assert.True(jobWorker.IsOpen()); while (TestService.Requests[typeof(ActivateJobsRequest)].Count < 2) { } } // then var actualRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualRequest); var actualSecondRequest = TestService.Requests[typeof(ActivateJobsRequest)][1]; Assert.AreEqual(expectedSecondRequest, actualSecondRequest); }
public void ShouldUseMultipleHandlerThreads() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 123_000L, MaxJobsToActivate = 3, Type = "foo", Worker = "jobWorker", RequestTimeout = 5_000L }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var signal = new EventWaitHandle(false, EventResetMode.AutoReset); var completedJobs = new ConcurrentDictionary <long, IJob>(); using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler(async(jobClient, job) => { await jobClient.NewCompleteJobCommand(job).Send(); completedJobs.TryAdd(job.Key, job); if (completedJobs.Count == 3) { signal.Set(); } }) .MaxJobsActive(3) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(123L)) .PollInterval(TimeSpan.FromMilliseconds(100)) .PollingTimeout(TimeSpan.FromSeconds(5L)) .HandlerThreads(3) .Open()) { Assert.True(jobWorker.IsOpen()); signal.WaitOne(); } // then var actualActivateRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualActivateRequest); var completeRequests = TestService.Requests[typeof(CompleteJobRequest)]; Assert.GreaterOrEqual(completeRequests.Count, 3); Assert.GreaterOrEqual(completedJobs.Count, 3); CollectionAssert.AreEquivalent(new List <long> { 1, 2, 3 }, completedJobs.Keys); }
public void ShouldSendRequestWithFetchVariablesList() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 10_000L, MaxJobsToActivate = 1, Type = "foo", Worker = "jobWorker", FetchVariable = { "foo", "bar", "test" } }; IList <string> variableNames = new List <string> { "foo", "bar", "test" }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var signal = new EventWaitHandle(false, EventResetMode.AutoReset); var receivedJobs = new List <IJob>(); using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { receivedJobs.Add(job); if (receivedJobs.Count == 3) { signal.Set(); } }) .MaxJobsActive(1) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(10)) .FetchVariables(variableNames) .PollInterval(TimeSpan.FromMilliseconds(100)) .Open()) { Assert.True(jobWorker.IsOpen()); signal.WaitOne(); } // then var actualRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualRequest); Assert.AreEqual(receivedJobs.Count, 3); AssertJob(receivedJobs[0], 1); AssertJob(receivedJobs[1], 2); AssertJob(receivedJobs[2], 3); }
public void ShouldSendFailCommandOnExceptionInJobHandler() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 123_000L, MaxJobsToActivate = 1, Type = "foo", Worker = "jobWorker" }; var expectedFailRequest = new FailJobRequest { JobKey = 1, ErrorMessage = "Job worker 'jobWorker' tried to handle job of type 'foo', but exception occured 'Fail'", Retries = 2 }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { if (job.Key == 1) { throw new Exception("Fail"); } }) .MaxJobsActive(1) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(123L)) .PollInterval(TimeSpan.FromMilliseconds(100)) .Open()) { Assert.True(jobWorker.IsOpen()); while (TestService.Requests[typeof(ActivateJobsRequest)].Count < 1 || TestService.Requests[typeof(FailJobRequest)].Count < 1) { } } // then var actualRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualRequest); var actualFailRequest = TestService.Requests[typeof(FailJobRequest)][0]; Assert.AreEqual(expectedFailRequest, actualFailRequest); }
public void ShouldUseAutoCompleteWithWorker() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 5_000L, MaxJobsToActivate = 3, Type = "foo", Worker = "jobWorker", RequestTimeout = 5_000L }; TestService.AddRequestHandler( typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { Logger.Info("Handler has seen job '{0}'", job); }) .AutoCompletion() .MaxJobsActive(3) .Name("jobWorker") .Timeout(TimeSpan.FromMilliseconds(5_000L)) .PollInterval(TimeSpan.FromSeconds(5)) .PollingTimeout(TimeSpan.FromMilliseconds(5_000L)) .Open()) { Assert.True(jobWorker.IsOpen()); while (TestService.Requests[typeof(CompleteJobRequest)].Count < 3) { } } // then var actualRequest = TestService.Requests[typeof(ActivateJobsRequest)][0]; Assert.AreEqual(expectedRequest, actualRequest); var completeJobRequests = TestService.Requests[typeof(CompleteJobRequest)].OfType <CompleteJobRequest>().Select(j => j.JobKey).ToList(); Assert.AreEqual(3, completeJobRequests.Count); Assert.Contains(1, completeJobRequests); Assert.Contains(2, completeJobRequests); Assert.Contains(3, completeJobRequests); }
public async Task ShouldSendMultipleDeployResourceAndGetResponseAsExpected() { // given var expectedResponse = new DeployProcessResponse { Key = 1 }; expectedResponse.Processes.Add(new ProcessMetadata { BpmnProcessId = "process", ResourceName = _demoProcessPath, Version = 1, ProcessDefinitionKey = 2 }); expectedResponse.Processes.Add(new ProcessMetadata { BpmnProcessId = "process2", ResourceName = _demoProcessPath, Version = 1, ProcessDefinitionKey = 3 }); TestService.AddRequestHandler(typeof(DeployProcessRequest), request => expectedResponse); // when var fileContent = File.ReadAllText(_demoProcessPath); var deployProcessResponse = await ZeebeClient.NewDeployCommand() .AddResourceFile(_demoProcessPath) .AddResourceString(fileContent, Encoding.UTF8, _demoProcessPath) .Send(); // then Assert.AreEqual(1, deployProcessResponse.Key); Assert.AreEqual(2, deployProcessResponse.Processes.Count); var processMetadata = deployProcessResponse.Processes[0]; Assert.AreEqual("process", processMetadata.BpmnProcessId); Assert.AreEqual(1, processMetadata.Version); Assert.AreEqual(_demoProcessPath, processMetadata.ResourceName); Assert.AreEqual(2, processMetadata.ProcessDefinitionKey); var processMetadata2 = deployProcessResponse.Processes[1]; Assert.AreEqual("process2", processMetadata2.BpmnProcessId); Assert.AreEqual(1, processMetadata2.Version); Assert.AreEqual(_demoProcessPath, processMetadata2.ResourceName); Assert.AreEqual(3, processMetadata2.ProcessDefinitionKey); }
public void ShouldSendRequestReceiveResponseAsExpected() { // given var expectedRequest = new ActivateJobsRequest { Timeout = 123L, Amount = 1, Type = "foo", Worker = "jobWorker" }; TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when var signal = new EventWaitHandle(false, EventResetMode.AutoReset); var receivedJobs = new List <IJob>(); using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler((jobClient, job) => { receivedJobs.Add(job); if (receivedJobs.Count == 3) { signal.Set(); } }) .Limit(1) .Name("jobWorker") .Timeout(123L) .PollInterval(TimeSpan.FromMilliseconds(100)) .Open()) { Assert.True(jobWorker.IsOpen()); signal.WaitOne(); } // then var actualRequest = TestService.Requests[0]; Assert.AreEqual(expectedRequest, actualRequest); Assert.AreEqual(receivedJobs.Count, 3); AssertJob(receivedJobs[0], 1); AssertJob(receivedJobs[1], 2); AssertJob(receivedJobs[2], 3); }
public async Task ShouldReceiveResponseAsExpected() { // given var expectedResponse = new SetVariablesResponse { Key = 12 }; TestService.AddRequestHandler(typeof(SetVariablesRequest), request => expectedResponse); // when var response = await ZeebeClient.NewSetVariablesCommand(2123).Variables("{\"foo\":\"bar\"}").Local().Send(); // then Assert.AreEqual(12, response.Key); }
public void ShouldNotRetrySendRequest() { // given TestService.AddRequestHandler( typeof(CancelProcessInstanceRequest), req => { throw new RpcException(new Status(StatusCode.Internal, "exhausted")); }); // when var resultTask = ZeebeClient.NewCancelInstanceCommand(12113).SendWithRetry(); var aggregateException = Assert.Throws <AggregateException>(() => resultTask.Wait()); var rpcException = (RpcException)aggregateException.InnerExceptions[0]; // then Assert.AreEqual(StatusCode.Internal, rpcException.Status.StatusCode); }
public async Task ShouldReceiveResponseAsExpected() { // given TopologyResponse expectedResponse = new TopologyResponse(); expectedResponse.Brokers.Add(CreateBrokerInfo(0, "host", 26501, 0, true)); expectedResponse.Brokers.Add(CreateBrokerInfo(1, "host", 26501, 0, false)); expectedResponse.Brokers.Add(CreateBrokerInfo(2, "host", 26501, 0, false)); TestService.AddRequestHandler(typeof(TopologyRequest), (request) => expectedResponse); // when ITopology response = await ZeebeClient.TopologyRequest().Send(); // then IBrokerInfo firstBroker = response.Brokers[0]; Assert.AreEqual("host0:26501", firstBroker.Address); Assert.AreEqual(0, firstBroker.NodeId); IPartitionInfo firstPartition = firstBroker.Partitions[0]; Assert.AreEqual(0, firstPartition.PartitionId); Assert.AreEqual(PartitionBrokerRole.LEADER, firstPartition.Role); IBrokerInfo secondBroker = response.Brokers[1]; Assert.AreEqual("host1:26501", secondBroker.Address); Assert.AreEqual(1, secondBroker.NodeId); firstPartition = secondBroker.Partitions[0]; Assert.AreEqual(0, firstPartition.PartitionId); Assert.AreEqual(PartitionBrokerRole.FOLLOWER, firstPartition.Role); IBrokerInfo thirdBroker = response.Brokers[2]; Assert.AreEqual("host2:26501", thirdBroker.Address); Assert.AreEqual(2, thirdBroker.NodeId); firstPartition = thirdBroker.Partitions[0]; Assert.AreEqual(0, firstPartition.PartitionId); Assert.AreEqual(PartitionBrokerRole.FOLLOWER, firstPartition.Role); }
public async Task shouldReceiveResponseAsExpected() { // given var expectedResponse = new ListWorkflowsResponse(); expectedResponse.Workflows.Add(new WorkflowMetadata { BpmnProcessId = "process", ResourceName = "file2.bpmn", Version = 1, WorkflowKey = 2 }); expectedResponse.Workflows.Add(new WorkflowMetadata { BpmnProcessId = "process2", ResourceName = "file.bpmn", Version = 1, WorkflowKey = 3 }); TestService.AddRequestHandler(typeof(ListWorkflowsRequest), request => expectedResponse); // when var response = await ZeebeClient.NewListWorkflowRequest().BpmnProcessId("process").Send(); // then Assert.AreEqual(2, response.WorkflowList.Count); var workflowMetadata = response.WorkflowList[0]; Assert.AreEqual("process", workflowMetadata.BpmnProcessId); Assert.AreEqual(1, workflowMetadata.Version); Assert.AreEqual("file2.bpmn", workflowMetadata.ResourceName); Assert.AreEqual(2, workflowMetadata.WorkflowKey); var workflowMetadata2 = response.WorkflowList[1]; Assert.AreEqual("process2", workflowMetadata2.BpmnProcessId); Assert.AreEqual(1, workflowMetadata2.Version); Assert.AreEqual("file.bpmn", workflowMetadata2.ResourceName); Assert.AreEqual(3, workflowMetadata2.WorkflowKey); }
public void ShouldNotRetrySendRequest <TReq, TRes, TClientResponse>( TReq expectedRequest, TRes response, RequestCreator <TClientResponse> requestCreator) where TRes : IMessage { // given TestService.AddRequestHandler( typeof(TReq), req => { throw new RpcException(new Status(StatusCode.Internal, "exhausted")); }); // when var resultTask = requestCreator(ZeebeClient).SendWithRetry(); var aggregateException = Assert.Throws <AggregateException>(() => resultTask.Wait()); var rpcException = (RpcException)aggregateException.InnerExceptions[0]; // then Assert.AreEqual(StatusCode.Internal, rpcException.Status.StatusCode); }
public void ShouldTimeoutRequest() { // given TestService.AddRequestHandler(typeof(CreateWorkflowInstanceWithResultRequest), request => { new EventWaitHandle(false, EventResetMode.AutoReset).WaitOne(); return(null); }); // when var task = ZeebeClient.NewCreateWorkflowInstanceCommand() .BpmnProcessId("process") .LatestVersion() .WithResult() .Send(TimeSpan.Zero); var aggregateException = Assert.Throws <AggregateException>(() => task.Wait(TimeSpan.FromSeconds(15))); var rpcException = (RpcException)aggregateException.InnerExceptions[0]; // then Assert.AreEqual(Grpc.Core.StatusCode.DeadlineExceeded, rpcException.Status.StatusCode); }
public void ShouldCompleteAfterSendFailCommandOnExceptionInJobHandler() { // given TestService.AddRequestHandler(typeof(ActivateJobsRequest), request => CreateExpectedResponse()); // when using (var jobWorker = ZeebeClient.NewWorker() .JobType("foo") .Handler(async(jobClient, job) => { if (job.Key == 2) { throw new Exception("Fail"); } await jobClient.NewCompleteJobCommand(job).Send(); }) .MaxJobsActive(3) .Name("jobWorker") .Timeout(TimeSpan.FromSeconds(123L)) .PollInterval(TimeSpan.FromMilliseconds(100)) .Open()) { Assert.True(jobWorker.IsOpen()); while (TestService.Requests[typeof(ActivateJobsRequest)].Count < 1 || TestService.Requests[typeof(FailJobRequest)].Count < 1 || TestService.Requests[typeof(CompleteJobRequest)].Count < 2) { } } // then var completeRequests = TestService.Requests[typeof(CompleteJobRequest)]; Assert.AreEqual(1, ((CompleteJobRequest)completeRequests[0]).JobKey); Assert.AreEqual(3, ((CompleteJobRequest)completeRequests[1]).JobKey); }