public async Task SearchActualBuilderAsyncTest(string searchTerm, string expectedComputedSearchTerm)
        {
            //Arrange
            //Reals
            var actualQueryBuilder = new DfcSearchQueryBuilder();
            var actualManipulator  = new JobProfileSearchManipulator();

            //Fakes
            var fakeIndexClient        = A.Fake <ISearchIndexClient>(o => o.Strict());
            var fakeQueryConverter     = A.Fake <IAzSearchQueryConverter>(o => o.Strict());
            var fakeDocumentsOperation = A.Fake <IDocumentsOperations>();
            var dummySearchProperty    = A.Dummy <SearchProperties>();
            var dummySearchParameters  = A.Dummy <SearchParameters>();
            var dummySearchResult      = A.Dummy <Data.Model.SearchResult <JobProfileIndex> >();
            var fakeLogger             = A.Fake <IApplicationLogger>();
            var policy = new TolerancePolicy(fakeLogger, new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider()));

            //Configure
            A.CallTo(() => fakeQueryConverter.BuildSearchParameters(A <SearchProperties> ._)).Returns(dummySearchParameters);
            A.CallTo(() => fakeIndexClient.Documents).Returns(fakeDocumentsOperation);
            A.CallTo(() => fakeQueryConverter.ConvertToSearchResult(A <DocumentSearchResult <JobProfileIndex> > ._, A <SearchProperties> ._)).Returns(dummySearchResult);

            //Act
            var searchService = new DfcSearchQueryService <JobProfileIndex>(fakeIndexClient, fakeQueryConverter, actualQueryBuilder, actualManipulator, fakeLogger);
            await searchService.SearchAsync(searchTerm, dummySearchProperty);

            //Assert
            A.CallTo(() => fakeQueryConverter.BuildSearchParameters(A <SearchProperties> ._)).MustHaveHappened();
            A.CallTo(() => fakeIndexClient.Documents).MustHaveHappened();
            A.CallTo(() => fakeDocumentsOperation.SearchWithHttpMessagesAsync <JobProfileIndex>(A <string> .That.Contains(expectedComputedSearchTerm), A <SearchParameters> ._, A <SearchRequestOptions> ._, A <Dictionary <string, List <string> > > ._, A <CancellationToken> ._)).MustHaveHappened();
            A.CallTo(() => fakeQueryConverter.ConvertToSearchResult(A <DocumentSearchResult <JobProfileIndex> > ._, A <SearchProperties> ._)).MustHaveHappened();
        }
        public async Task GetServiceStatusExceptionAsync()
        {
            //Arrange
            var fakeHttpClientService = A.Fake <IHttpClientService <ISpellcheckService> >(ops => ops.Strict());
            var fakeLogger            = A.Fake <IApplicationLogger>(ops => ops.Strict());
            var policy = new TolerancePolicy(fakeLogger, new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider()));
            var json   = "{\"_type\": \"Cause Exception\"}";
            var fakeHttpResponseMessage = new HttpResponseMessage
            {
                Content      = new StringContent(json, Encoding.UTF8, "application/json"),
                StatusCode   = System.Net.HttpStatusCode.ServiceUnavailable,
                ReasonPhrase = nameof(GetServiceStatusAsync)
            };

            A.CallTo(() => fakeHttpClientService.GetAsync(A <string> ._, A <FaultToleranceType> ._)).Returns(fakeHttpResponseMessage);
            A.CallTo(() => fakeHttpClientService.AddHeader(Constants.OcpApimSubscriptionKey, A <string> ._)).Returns(true);
            A.CallTo(() => fakeLogger.LogExceptionWithActivityId(A <string> ._, A <Exception> ._)).Returns("Exception logged");

            //Act
            var spellingService = new SpellCheckService(fakeHttpClientService, fakeLogger);
            var serviceStatus   = await spellingService.GetCurrentStatusAsync();

            //Asserts
            serviceStatus.Status.Should().NotBe(ServiceState.Green);
            serviceStatus.Notes.Should().Contain("Exception logged");
            A.CallTo(() => fakeLogger.LogExceptionWithActivityId(A <string> ._, A <Exception> ._)).MustHaveHappened();
        }
        public async Task GetServiceStatusAsync(bool suggestionsReturned, ServiceState expectedServiceStatus, bool isResponseSuccess)
        {
            //Arrange
            var fakeHttpClientService = A.Fake <IHttpClientService <ISpellcheckService> >(ops => ops.Strict());
            var fakeLogger            = A.Fake <IApplicationLogger>();
            var policy = new TolerancePolicy(fakeLogger, new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider()));

            var json = suggestionsReturned ? "{\"_type\": \"SpellCheck\", \"flaggedTokens\": [{\"offset\": 0, \"token\": \"pluse\", \"type\": \"UnknownToken\", \"suggestions\": [{\"suggestion\": \"pulse\", \"score\": 1}]}]}\r\n" : "{\"_type\": \"SpellCheck\", \"flaggedTokens\": []}";
            var fakeHttpResponseMessage = new HttpResponseMessage
            {
                Content      = new StringContent(json, Encoding.UTF8, "application/json"),
                StatusCode   = isResponseSuccess ? System.Net.HttpStatusCode.OK : System.Net.HttpStatusCode.ServiceUnavailable,
                ReasonPhrase = nameof(GetServiceStatusAsync)
            };

            //Setup Dummies and Mocks
            A.CallTo(() => fakeHttpClientService.GetAsync(A <string> ._, A <FaultToleranceType> ._)).Returns(fakeHttpResponseMessage);
            A.CallTo(() => fakeHttpClientService.AddHeader(Constants.OcpApimSubscriptionKey, A <string> ._)).Returns(true);

            //Act
            var spellingService = new SpellCheckService(fakeHttpClientService, fakeLogger);
            var serviceStatus   = await spellingService.GetCurrentStatusAsync();

            //Asserts
            serviceStatus.Status.Should().Be(expectedServiceStatus);
        }
        public async Task CheckSpellingAsyncTest(string term, bool suggestionsReturned, bool isResponseSuccess)
        {
            //Arrange
            var fakeHttpClientService = A.Fake <IHttpClientService <ISpellcheckService> >(ops => ops.Strict());
            var fakeLogger            = A.Fake <IApplicationLogger>();
            var policy = new TolerancePolicy(fakeLogger, new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider()));

            var json = suggestionsReturned ? "{\"_type\": \"SpellCheck\", \"flaggedTokens\": [{\"offset\": 0, \"token\": \"pluse\", \"type\": \"UnknownToken\", \"suggestions\": [{\"suggestion\": \"pulse\", \"score\": 1}]}]}\r\n" : "{\"_type\": \"SpellCheck\", \"flaggedTokens\": []}";
            var fakeHttpResponseMessage = new HttpResponseMessage
            {
                Content    = new StringContent(json, Encoding.UTF8, "application/json"),
                StatusCode = isResponseSuccess ? System.Net.HttpStatusCode.OK : System.Net.HttpStatusCode.ServiceUnavailable
            };

            A.CallTo(() => fakeHttpClientService.GetAsync(A <string> ._, A <FaultToleranceType> ._)).Returns(fakeHttpResponseMessage);
            A.CallTo(() => fakeHttpClientService.AddHeader(Constants.OcpApimSubscriptionKey, A <string> ._)).Returns(true);

            //Act
            var spellingService = new SpellCheckService(fakeHttpClientService, fakeLogger);
            var result          = await spellingService.CheckSpellingAsync(term);

            //Assert
            if (isResponseSuccess && suggestionsReturned)
            {
                result.HasCorrected.Should().BeTrue();
            }
            else
            {
                result.HasCorrected.Should().BeFalse();
            }
        }
Example #5
0
        public void ExecuteTestWithPredicate(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.WaitRetry:
            case FaultToleranceType.RetryWithCircuitBreaker:
                var         executedNumberOfTimes = 0;
                Func <Task> result2 = async() =>
                {
                    await actor.ExecuteAsync(
                        () => Task.FromResult(executedNumberOfTimes++),
                        a => a < strategy.Retry,
                        dependencyName,
                        toleranceType);
                };

                result2.Awaiting(async a => await a()).Should().NotThrow();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.CircuitBreaker:

                Func <Task> result3 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() => ThrowEx(), a => idx < strategy.AllowedFaults, dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };
                result3.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }
        public async Task SearchAsyncTest()
        {
            //Arrange
            var fakeIndexClient        = A.Fake <ISearchIndexClient>(o => o.Strict());
            var fakeQueryBuilder       = A.Fake <ISearchQueryBuilder>(o => o.Strict());
            var fakeQueryConverter     = A.Fake <IAzSearchQueryConverter>(o => o.Strict());
            var fakeDocumentsOperation = A.Fake <IDocumentsOperations>();
            var dummySearchProperty    = A.Dummy <SearchProperties>();
            var dummySearchParameters  = A.Dummy <SearchParameters>();
            var dummySearchResult      = A.Dummy <Data.Model.SearchResult <JobProfileIndex> >();
            var fakeLogger             = A.Fake <IApplicationLogger>();
            var fakeManipulator        = A.Fake <ISearchManipulator <JobProfileIndex> >();
            var policy = new TolerancePolicy(fakeLogger, new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider()));

            //Configure
            A.CallTo(() => fakeQueryBuilder.RemoveSpecialCharactersFromTheSearchTerm(A <string> ._, A <SearchProperties> ._)).Returns(CleanedSearchTerm);
            A.CallTo(() => fakeQueryBuilder.BuildContainPartialSearch(A <string> ._, A <SearchProperties> ._)).Returns(PartialTermToSearch);
            A.CallTo(() => fakeQueryBuilder.TrimCommonWordsAndSuffixes(A <string> ._, A <SearchProperties> ._)).Returns(TrimmedResults);
            A.CallTo(() => fakeQueryConverter.BuildSearchParameters(A <SearchProperties> ._)).Returns(dummySearchParameters);
            A.CallTo(() => fakeIndexClient.Documents).Returns(fakeDocumentsOperation);
            A.CallTo(() => fakeQueryConverter.ConvertToSearchResult(A <DocumentSearchResult <JobProfileIndex> > ._, A <SearchProperties> ._)).Returns(dummySearchResult);
            A.CallTo(() => fakeManipulator.BuildSearchExpression(A <string> ._, A <string> ._, A <string> ._, A <SearchProperties> ._)).Returns(nameof(fakeManipulator.BuildSearchExpression));

            //Act
            var searchService = new DfcSearchQueryService <JobProfileIndex>(fakeIndexClient, fakeQueryConverter, fakeQueryBuilder, fakeManipulator, fakeLogger);
            await searchService.SearchAsync("searchTerm", dummySearchProperty);

            //Assert
            A.CallTo(() => fakeQueryBuilder.RemoveSpecialCharactersFromTheSearchTerm(A <string> .That.IsEqualTo(SearchTerm), A <SearchProperties> ._)).MustHaveHappened();
            A.CallTo(() => fakeQueryBuilder.TrimCommonWordsAndSuffixes(A <string> .That.IsEqualTo(CleanedSearchTerm), A <SearchProperties> ._)).MustHaveHappened();
            A.CallTo(() => fakeQueryBuilder.BuildContainPartialSearch(A <string> .That.IsEqualTo(TrimmedResults), A <SearchProperties> ._)).MustHaveHappened();
            A.CallTo(() => fakeQueryConverter.BuildSearchParameters(A <SearchProperties> ._)).MustHaveHappened();
            A.CallTo(() => fakeIndexClient.Documents).MustHaveHappened();
            A.CallTo(() => fakeDocumentsOperation.SearchWithHttpMessagesAsync <JobProfileIndex>(A <string> .That.IsEqualTo(nameof(fakeManipulator.BuildSearchExpression)), A <SearchParameters> ._, A <SearchRequestOptions> ._, A <Dictionary <string, List <string> > > ._, A <CancellationToken> ._)).MustHaveHappened();
            A.CallTo(() => fakeQueryConverter.ConvertToSearchResult(A <DocumentSearchResult <JobProfileIndex> > ._, A <SearchProperties> ._)).MustHaveHappened();
        }
Example #7
0
        public void ExecuteTest(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.Timeout:
                Action result1 = () => actor.Execute(() =>
                {
                    SystemClock.Sleep(TimeSpan.FromSeconds(strategy.Timeout.Seconds + 1), CancellationToken.None);
                    return(dependencyName);
                },
                                                     dependencyName,
                                                     toleranceType);

                result1.Should().Throw <TimeoutRejectedException>();
                break;

            case FaultToleranceType.Retry:
                var    executedNumberOfTimes = 0;
                Action result2 = () => actor.Execute(() =>
                {
                    executedNumberOfTimes++;
                    return(ThrowEx());
                },
                                                     dependencyName,
                                                     toleranceType);

                result2.Should().Throw <NotImplementedException>();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.WaitRetry:
                TimeSpan delayResult     = default;
                var      exNumberOfTimes = 0;
                Action   resultWait      = () =>
                {
                    var delay = Stopwatch.StartNew();
                    try
                    {
                        actor.Execute(
                            () =>
                        {
                            exNumberOfTimes++;
                            return(ThrowEx());
                        },
                            dependencyName,
                            toleranceType);
                    }
                    finally
                    {
                        delay.Stop();
                        delayResult = delay.Elapsed;
                    }
                };

                resultWait.Should().Throw <NotImplementedException>();
                exNumberOfTimes.Should().Be(strategy.Retry + 1);
                delayResult.Should().BeCloseTo(TimeSpan.FromSeconds(strategy.Wait.Seconds * strategy.Retry), Precision);
                break;

            case FaultToleranceType.CircuitBreaker:
                Action result3 = () =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            actor.Execute(() => ThrowEx(), dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result3.Should().Throw <BrokenCircuitException>();
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                var    retriedBeforeBreakingCircuit = 0;
                Action result4 = () =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            actor.Execute(() =>
                            {
                                retriedBeforeBreakingCircuit++;
                                return(ThrowEx());
                            },
                                          dependencyName,
                                          toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result4.Should().Throw <BrokenCircuitException>();
                retriedBeforeBreakingCircuit.Should().Be(strategy.AllowedFaults * (strategy.Retry + 1));
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }
Example #8
0
        public void ExecuteAsyncTest(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.Timeout:
                Func <Task> result1 = async() => await actor.ExecuteAsync(() => SystemClock.SleepAsync(TimeSpan.FromSeconds(strategy.Timeout.Seconds + 1), CancellationToken.None).ContinueWith(_ => dependencyName), dependencyName, toleranceType);

                result1.Awaiting(async a => await a()).Should().Throw <TimeoutRejectedException>();
                break;

            case FaultToleranceType.Retry:
                var         executedNumberOfTimes = 0;
                Func <Task> result2 = async() => await actor.ExecuteAsync(() =>
                {
                    executedNumberOfTimes++;
                    return(ThrowEx());
                },
                                                                          dependencyName,
                                                                          toleranceType);

                result2.Awaiting(async a => await a()).Should().Throw <NotImplementedException>();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.CircuitBreaker:
                Func <Task> result3 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() => ThrowEx(), dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result3.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                var         retriedBeforeBreakingCircuit = 0;
                Func <Task> result4 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() =>
                            {
                                retriedBeforeBreakingCircuit++;
                                return(ThrowEx());
                            },
                                                     dependencyName,
                                                     toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result4.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                retriedBeforeBreakingCircuit.Should().Be(strategy.AllowedFaults * (strategy.Retry + 1));
                break;

            case FaultToleranceType.WaitRetry:
                var         exNumberOfTimes = 0;
                Func <Task> result5         = async() =>
                {
                    await actor.ExecuteAsync(
                        () =>
                    {
                        exNumberOfTimes++;
                        return(ThrowEx());
                    },
                        dependencyName,
                        toleranceType);
                };

                result5.Awaiting(async a => await a()).Should().Throw <NotImplementedException>();
                exNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }