コード例 #1
0
    public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Templated_Json()
    {
        // Arrange
        var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

        var templateValues = new Dictionary <string, string>()
        {
            ["AvatarUrl"] = "https://avatars.githubusercontent.com/u/1516790?v=4",
            ["BlogUrl"]   = "https://tech.justeattakeaway.com/",
        };

        // Act
        options.RegisterBundle(Path.Join("Bundles", "templated-bundle-json.json"), templateValues);

        // Assert
        string content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat");

        content
        .Replace(" ", string.Empty, StringComparison.Ordinal)
        .Replace("\n", string.Empty, StringComparison.Ordinal)
        .Replace("\r", string.Empty, StringComparison.Ordinal)
        .ShouldBe(@"{""id"":1516790,""login"":""justeat"",""url"":""https://api.github.com/orgs/justeat"",""avatar_url"":""https://avatars.githubusercontent.com/u/1516790?v=4"",""name"":""JustEatTakeaway"",""blog"":""https://tech.justeattakeaway.com/""}");

        // Assert
        content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat/repos");

        content
        .Replace(" ", string.Empty, StringComparison.Ordinal)
        .Replace("\n", string.Empty, StringComparison.Ordinal)
        .Replace("\r", string.Empty, StringComparison.Ordinal)
        .ShouldBe(@"[{""id"":123456,""name"":""httpclient-interception"",""full_name"":""justeat/httpclient-interception"",""private"":false,""owner"":{""login"":""justeat"",""id"":1516790}}]");
    }
コード例 #2
0
        public static async Task Can_Skip_Bundle_Items()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "skipped-item-bundle.json"));

            // Assert
            await Assert.ThrowsAsync <HttpRequestNotInterceptedException>(
                () => HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/"));
        }
コード例 #3
0
    public static async Task Can_Use_Extensibility_For_Request_Header_Matching()
    {
        // Arrange
        var builder = new HttpRequestInterceptionBuilder()
                      .ForHttps()
                      .ForHost("api.github.com")
                      .ForPath("orgs/justeat/repos")
                      .ForQuery("type=private");

        var options = new HeaderMatchingOptions(
            (p) => p.Accept.FirstOrDefault()?.MediaType == "application/vnd.github.v3+json" &&
            p.Authorization?.Scheme == "token" &&
            p.Authorization?.Parameter == "my-token" &&
            p.UserAgent?.FirstOrDefault()?.Product.Name == "My-App" &&
            p.UserAgent?.FirstOrDefault()?.Product.Version == "1.0.0");

        options.Register(builder);

        var url     = "https://api.github.com/orgs/justeat/repos?type=private";
        var headers = new Dictionary <string, string>()
        {
            ["accept"]        = "application/vnd.github.v3+json",
            ["authorization"] = "token my-token",
            ["user-agent"]    = "My-App/1.0.0",
        };

        // Act and Assert
        await HttpAssert.GetAsync(options, url, headers : headers);

        await Should.ThrowAsync <HttpRequestException>(() => HttpAssert.GetAsync(options, url));

        // Arrange
        headers = new Dictionary <string, string>()
        {
            ["accept"]        = "application/vnd.github.v3+json",
            ["authorization"] = "token my-token",
            ["user-agent"]    = "My-App/2.0.0",
        };

        // Act and Assert
        await Should.ThrowAsync <HttpRequestException>(() => HttpAssert.GetAsync(options, url, headers: headers));

        // Arrange
        headers = new Dictionary <string, string>()
        {
            ["accept"]     = "application/vnd.github.v3+json",
            ["user-agent"] = "My-App/1.0.0",
        };

        // Act and Assert
        await Should.ThrowAsync <HttpRequestException>(() => HttpAssert.GetAsync(options, url, headers: headers));
    }
コード例 #4
0
    public static async Task Options_Can_Be_Cloned()
    {
        // Arrange
        var url     = "https://google.com/";
        var payload = new MyObject()
        {
            Message = "Hello world!"
        };

        var options = new HttpClientInterceptorOptions()
                      .RegisterGetJson(url, payload, statusCode: HttpStatusCode.NotFound);

        // Act
        var clone = options.Clone()
                    .RegisterGetJson(url, payload, statusCode: HttpStatusCode.InternalServerError);

        // Assert
        clone.OnMissingRegistration.ShouldBe(options.OnMissingRegistration);
        clone.OnSend.ShouldBe(options.OnSend);
        clone.ThrowOnMissingRegistration.ShouldBe(options.ThrowOnMissingRegistration);

        await HttpAssert.GetAsync(options, url, HttpStatusCode.NotFound);

        await HttpAssert.GetAsync(clone, url, HttpStatusCode.InternalServerError);

        // Arrange
        options.OnMissingRegistration = (_) => Task.FromResult <HttpResponseMessage>(null);
        options.OnSend = (_) => Task.CompletedTask;
        options.ThrowOnMissingRegistration = true;
        options.Clear();

        // Act and Assert
        clone.ThrowOnMissingRegistration.ShouldNotBe(options.ThrowOnMissingRegistration);
        clone.OnMissingRegistration.ShouldNotBe(options.OnMissingRegistration);
        clone.OnSend.ShouldNotBe(options.OnSend);

        await Should.ThrowAsync <HttpRequestNotInterceptedException>(() => HttpAssert.GetAsync(options, url, HttpStatusCode.InternalServerError));

        await HttpAssert.GetAsync(clone, url, HttpStatusCode.InternalServerError);

        // Arrange
        options = new HttpClientInterceptorOptions()
                  .ThrowsOnMissingRegistration();

        // Act
        clone = options.Clone();

        // Assert
        clone.ThrowOnMissingRegistration.ShouldBe(options.ThrowOnMissingRegistration);
        clone.OnMissingRegistration.ShouldBe(options.OnMissingRegistration);
        clone.OnSend.ShouldBe(options.OnSend);
    }
コード例 #5
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_If_No_Content()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "no-content.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/");

            content.ShouldBe(string.Empty);
        }
コード例 #6
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_String_Encoded_As_Base64()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "content-as-html-base64.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/");

            content.ShouldBe("<html><head><title>Just Eat</title></head></html>");
        }
コード例 #7
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Non_Default_Status_Codes()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "http-status-codes.json"));

            // Assert
            await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/1", HttpStatusCode.NotFound);

            await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/2", HttpStatusCode.NotFound);
        }
コード例 #8
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Null_Json()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "content-as-null-json.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat");

            content.ShouldBe(string.Empty);
        }
    public static async Task RegisterGet_For_Plaintext_String_With_Custom_Status_Code_Registers_Interception()
    {
        // Arrange
        string requestUri = "https://google.com/";
        string expected   = "foo";

        var options = new HttpClientInterceptorOptions().RegisterGet(requestUri, expected);

        // Act
        string actual = await HttpAssert.GetAsync(options, requestUri);

        // Assert
        actual.ShouldBe(expected);
    }
    public static async Task RegisterGet_For_Html_With_Custom_Media_Type_Registers_Interception()
    {
        // Arrange
        string requestUri = "https://google.com/";
        string mediaType  = "text/html";
        string expected   = "<html>foo></html>";

        var options = new HttpClientInterceptorOptions().RegisterGet(requestUri, expected, mediaType: mediaType);

        // Act
        string actual = await HttpAssert.GetAsync(options, requestUri, mediaType : mediaType);

        // Assert
        actual.ShouldBe(expected);
    }
    public static async Task RegisterGet_If_Content_String_Is_Null_Registers_Interception()
    {
        // Arrange
        string requestUri = "https://google.com/";
        string content    = null;
        string expected   = string.Empty;

        var options = new HttpClientInterceptorOptions().RegisterGet(requestUri, content);

        // Act
        string actual = await HttpAssert.GetAsync(options, requestUri);

        // Assert
        actual.ShouldBe(expected);
    }
    public static async Task RegisterGetJson_For_With_Defaults_Registers_Interception()
    {
        // Arrange
        string requestUri = "https://google.com/";

        string[] expected = new[] { "foo", "bar" };

        var options = new HttpClientInterceptorOptions().RegisterGetJson(requestUri, expected);

        // Act
        string[] actual = await HttpAssert.GetAsync <string[]>(options, requestUri);

        // Assert
        actual.ShouldBe(expected);
    }
コード例 #13
0
    public static async Task SendAsync_Calls_OnMissingRegistration_With_RequestMessage()
    {
        // Arrange
        var header     = "x-request";
        var requestUrl = "https://google.com/foo";

        var options = new HttpClientInterceptorOptions();

        int expected = 7;
        int actual   = 0;

        var requestIds = new ConcurrentBag <string>();

        options.OnMissingRegistration = (p) =>
        {
            Interlocked.Increment(ref actual);
            requestIds.Add(p.Headers.GetValues(header).FirstOrDefault());

            var response = new HttpResponseMessage(HttpStatusCode.Accepted)
            {
                Content = new StringContent(string.Empty),
            };

            return(Task.FromResult(response));
        };

        Task GetAsync(int id)
        {
            var headers = new Dictionary <string, string>()
            {
                [header] = id.ToString(CultureInfo.InvariantCulture),
            };

            return(HttpAssert.GetAsync(options, requestUrl, HttpStatusCode.Accepted, headers: headers));
        }

        // Act
        var tasks = Enumerable.Range(0, expected)
                    .Select(GetAsync)
                    .ToArray();

        await Task.WhenAll(tasks);

        // Assert
        actual.ShouldBe(expected);
        requestIds.Count.ShouldBe(expected);
        requestIds.ShouldBeUnique();
    }
コード例 #14
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Templated_Json()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "templated-bundle-json.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat");

            content
            .Replace(" ", string.Empty, StringComparison.Ordinal)
            .Replace("\n", string.Empty, StringComparison.Ordinal)
            .Replace("\r", string.Empty, StringComparison.Ordinal)
            .ShouldBe(@"{""id"":1516790,""login"":""justeat"",""url"":""https://api.github.com/orgs/justeat""}");
        }
コード例 #15
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Json_Array()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "content-as-json-array.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat/repos");

            content
            .Replace(" ", string.Empty, StringComparison.Ordinal)
            .Replace("\n", string.Empty, StringComparison.Ordinal)
            .Replace("\r", string.Empty, StringComparison.Ordinal)
            .ShouldBe(@"[""httpclient-interception""]");
        }
コード例 #16
0
        public static async Task Can_Intercept_Http_Requests_With_Different_Path_If_The_Uri_Query_String()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            // Act
            options.RegisterBundle(Path.Join("Bundles", "ignoring-query.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat?foo=bar");

            content
            .Replace(" ", string.Empty, StringComparison.Ordinal)
            .Replace("\n", string.Empty, StringComparison.Ordinal)
            .Replace("\r", string.Empty, StringComparison.Ordinal)
            .ShouldBe(@"{""id"":1516790,""login"":""justeat"",""url"":""https://api.github.com/orgs/justeat""}");
        }
コード例 #17
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File_With_Templated_String()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            var headers = new Dictionary <string, string>()
            {
                { "user-agent", "My-App/1.0.0" },
            };

            // Act
            options.RegisterBundle(Path.Join("Bundles", "templated-bundle-string.json"));

            // Assert
            string content = await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/", headers : headers);

            content.ShouldBe("<html><head><title>Just Eat</title></head></html>");
        }
コード例 #18
0
    public static async Task HttpClient_Registrations_Can_Be_Removed()
    {
        // Arrange
        var options = new HttpClientInterceptorOptions()
                      .RegisterGetJson("https://google.com/", new { message = "Hello world!" })
                      .RegisterGetJson("https://google.co.uk/", new { message = "Hello world!" });

        // Act and Assert
        await HttpAssert.GetAsync(options, "https://google.com/");

        await HttpAssert.GetAsync(options, "https://google.com/");

        await HttpAssert.GetAsync(options, "https://google.co.uk/");

        await HttpAssert.GetAsync(options, "https://google.co.uk/");

        // Arrange
        options.DeregisterGet("https://google.com/")
        .DeregisterGet("https://google.com/");

        // Act and Assert
        await Should.ThrowAsync <HttpRequestException>(() => HttpAssert.GetAsync(options, "https://google.com/"));

        await Should.ThrowAsync <HttpRequestException>(() => HttpAssert.GetAsync(options, "https://google.com/"));

        await HttpAssert.GetAsync(options, "https://google.co.uk/");

        await HttpAssert.GetAsync(options, "https://google.co.uk/");

        // Arrange
        var builder = new HttpRequestInterceptionBuilder()
                      .ForHttps()
                      .ForGet()
                      .ForHost("bing.com");

        options.ThrowOnMissingRegistration = true;
        options.Register(builder);

        await HttpAssert.GetAsync(options, "https://bing.com/");

        options.Deregister(builder);

        await Should.ThrowAsync <HttpRequestNotInterceptedException>(() => HttpAssert.GetAsync(options, "https://bing.com/"));
    }
コード例 #19
0
    public static async Task SendAsync_Calls_OnSend_With_RequestMessage()
    {
        // Arrange
        var header     = "x-request";
        var requestUrl = "https://google.com/foo";

        var options = new HttpClientInterceptorOptions()
                      .RegisterByteArray(HttpMethod.Get, new Uri(requestUrl), () => Array.Empty <byte>());

        int expected = 7;
        int actual   = 0;

        var requestIds = new ConcurrentBag <string>();

        options.OnSend = (p) =>
        {
            Interlocked.Increment(ref actual);
            requestIds.Add(p.Headers.GetValues(header).FirstOrDefault());
            return(Task.CompletedTask);
        };

        Task GetAsync(int id)
        {
            var headers = new Dictionary <string, string>()
            {
                [header] = id.ToString(CultureInfo.InvariantCulture),
            };

            return(HttpAssert.GetAsync(options, requestUrl, headers: headers));
        }

        // Act
        var tasks = Enumerable.Range(0, expected)
                    .Select(GetAsync)
                    .ToArray();

        await Task.WhenAll(tasks);

        // Assert
        actual.ShouldBe(expected);
        requestIds.Count.ShouldBe(expected);
        requestIds.ShouldBeUnique();
    }
コード例 #20
0
    public static async Task Options_Can_Be_Scoped()
    {
        // Arrange
        var url     = "https://google.com/";
        var payload = new MyObject()
        {
            Message = "Hello world!"
        };

        var options = new HttpClientInterceptorOptions()
                      .RegisterGetJson(url, payload, statusCode: HttpStatusCode.NotFound);

        // Act - begin first scope
        using (options.BeginScope())
        {
            // Assert - original registration
            await HttpAssert.GetAsync(options, url, HttpStatusCode.NotFound);

            // Arrange - first update to registration
            options.RegisterGetJson(url, payload, statusCode: HttpStatusCode.InternalServerError);

            // Assert - first updated registration
            await HttpAssert.GetAsync(options, url, HttpStatusCode.InternalServerError);

            // Act - begin second scope
            using (options.BeginScope())
            {
                // Arrange - second update to registration
                options.RegisterGetJson(url, payload, statusCode: HttpStatusCode.RequestTimeout);

                // Assert - second updated registration
                await HttpAssert.GetAsync(options, url, HttpStatusCode.RequestTimeout);
            }

            // Assert - first updated registration
            await HttpAssert.GetAsync(options, url, HttpStatusCode.InternalServerError);
        }

        // Assert - original registration
        await HttpAssert.GetAsync(options, url, HttpStatusCode.NotFound);
    }
コード例 #21
0
        public static async Task Can_Intercept_Http_Requests_From_Bundle_File()
        {
            // Arrange
            var options = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();

            var headers = new Dictionary <string, string>()
            {
                { "accept", "application/vnd.github.v3+json" },
                { "authorization", "token my-token" },
                { "user-agent", "My-App/1.0.0" },
            };

            // Act
            options.RegisterBundle(Path.Join("Bundles", "http-request-bundle.json"));

            // Assert
            await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/", mediaType : "text/html");

            await HttpAssert.GetAsync(options, "https://www.just-eat.co.uk/order-history");

            await HttpAssert.GetAsync(options, "https://api.github.com/orgs/justeat", headers : headers, mediaType : "application/json");
        }