public async Task ItInvokesOnStart()
            {
                // Arrange
                var host = new TestServiceHost();
                var container = CreateTestContainer();
                var service = new TestService(TestName, host);

                // Act
                await service.Start(container);

                // Assert
                Assert.True(service.WasStarted);
            }
            public async Task GivenNoJobWithName_ItThrowsUnknownJobException()
            {
                // Arrange
                var host = new TestServiceHost();
                host.Initialize();

                var dispatcher = new JobDispatcher(Enumerable.Empty<JobDescription>(), host.Container);
                var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "flarg", "test", new Dictionary<string, string>());
                var context = new InvocationContext(invocation, queue: null);

                // Act/Assert
                var ex = await AssertEx.Throws<UnknownJobException>(() => dispatcher.Dispatch(context));
                Assert.Equal("flarg", ex.JobName);
            }
            public async Task ItConfiguresShutdownTokenToCallOnShutdown()
            {
                // Arrange
                var host = new TestServiceHost();
                var container = CreateTestContainer();
                var service = new TestService(TestName, host);
                await service.Start(container);

                // Act
                host.Shutdown();

                // Assert
                Assert.True(service.WasShutdown);
            }
            public async Task ItInjectsPropertiesWithPublicSetters()
            {
                // Arrange
                var host = new TestServiceHost();
                var container = CreateTestContainer();
                var service = new TestServiceWithComponents(TestName, host);

                // Act
                await service.Start(container);

                // Assert
                Assert.Same(service.Something, container.Resolve<SomeComponent>());
                Assert.Null(service.SomethingElse);
            }
            public async Task GivenJobWithName_ItInvokesTheJobAndReturnsTheResult()
            {
                // Arrange
                var host = new TestServiceHost();
                host.Initialize();

                var job = new JobDescription("test", typeof(TestJob));

                var dispatcher = new JobDispatcher(new[] { job }, host.Container);
                var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "Test", "test", new Dictionary<string, string>());
                var context = new InvocationContext(invocation, queue: null);
                var expected = InvocationResult.Completed();
                TestJob.SetTestResult(expected);

                // Act
                var actual = await dispatcher.Dispatch(context);

                // Assert
                Assert.Same(expected, actual);
            }
            public async Task GivenJobWithConstructorArgs_ItResolvesThemFromTheContainer()
            {
                // Arrange
                var expected = new SomeService();
                var host = new TestServiceHost(
                    componentRegistrations: b => {
                        b.RegisterInstance(expected).As<SomeService>();
                    });
                host.Initialize();

                var job = new JobDescription("test", typeof(TestJobWithService));

                var dispatcher = new JobDispatcher(new[] { job }, host.Container);
                var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "Test", "test", new Dictionary<string, string>());
                var context = new InvocationContext(invocation, queue: null);
                var slot = new ContextSlot();
                TestJobWithService.SetContextSlot(slot);
                
                // Act
                await dispatcher.Dispatch(context);
                
                // Assert
                Assert.Same(expected, slot.Value);
            }
            public async Task GivenAContinuationRequest_ItCallsTheInvokeContinuationMethod()
            {
                // Arrange
                var host = new TestServiceHost();
                host.Initialize();

                var job = new JobDescription("test", typeof(TestAsyncJob));

                var dispatcher = new JobDispatcher(new[] { job }, host.Container);
                var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "Test", "test", new Dictionary<string, string>(), isContinuation: true);
                var context = new InvocationContext(invocation, queue: null);
                
                // Act
                var result = await dispatcher.Dispatch(context);

                // Assert
                Assert.Equal(ExecutionResult.Completed, result.Result);
            }
            public async Task GivenAContinuationRequestToANonAsyncJob_ItThrows()
            {
                // Arrange
                var host = new TestServiceHost();
                 host.Initialize();

                var job = new JobDescription("test", typeof(TestJob));

                var dispatcher = new JobDispatcher(new[] { job }, host.Container);
                var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "Test", "test", new Dictionary<string, string>(), isContinuation: true);
                var context = new InvocationContext(invocation, queue: null);

                // Act/Assert
                var ex = await AssertEx.Throws<InvalidOperationException>(() => dispatcher.Dispatch(context));
                Assert.Equal(String.Format(
                    Strings.JobDispatcher_AsyncContinuationOfNonAsyncJob,
                    job.Name), ex.Message);
            }