简体   繁体   中英

UWP Windows.Web.HttpClient fake for unit test

I try to do unit-test REST communication logic for UWP client. With reference to the answer for System.Web.HttpClient , I found that Windows.Net.HttpClient also accepts an arguement called IHttpFilter .

So, I try to make custom response with IHttpFilter but I don't know correct way to make a response.

    public class TestFilter : IHttpFilter
    {
        public IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> SendRequestAsync(HttpRequestMessage request)
        {
            if (request.Method == HttpMethod.Get)
            {
                // response fake response for GET...
            }
        }

        public void Dispose()
        {
            // do nothing
        }
    }           

And the target method for unit-test is as below.

    public async Task<string> PostResult(HttpClient httpClient, string username)
    {
        var json = new JsonObject
        {
            {"Username",
                JsonValue.CreateStringValue(string.IsNullOrEmpty(username) ? CommonKey.UnAuthorizedUserPartitionKey : username)
            },
        };

        var content = new HttpStringContent(json.Stringify());
        content.Headers.ContentType = new HttpMediaTypeHeaderValue("application/json");

        // I want to make below line testable...
        var response = await httpClient.PostAsync(new Uri(Common.ProcessUrl), content);
        try
        {
            response.EnsureSuccessStatusCode();
            return null;
        }
        catch (Exception exception)
        {
            return exception.Message ?? "EMPTY ERROR MESSAGE";
        }
    }

Note that It's NOT duplicate question related to System.Web.HttpClient mocking/faking. What I ask is Windows.Web.HttpClient specifically. I failed to implement with it.

Note that, Windows.Web.Http.IHttpClient is internal accessible and HttpClient is sealed. So hard to do Mock or inherit-and-override it.

While I agree with some that there are better ways to test HttpClient calls, I'll answer your question of how to create a "fake" response with an IHttpFilter implementation (System.Runtime.InteropServices.WindowsRuntime is your friend)

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Web.Http;
using Windows.Web.Http.Filters;

namespace Project.UnitTesting
{
    public class FakeResponseFilter : IHttpFilter
    {
        private readonly Dictionary<Uri, HttpResponseMessage> _fakeResponses = new Dictionary<Uri, HttpResponseMessage>();

        public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
        {
            _fakeResponses.Add(uri, responseMessage);
        }

        public void Dispose()
        {
            // Nothing to dispose
        }

        public IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> SendRequestAsync(HttpRequestMessage request)
        {
            if (_fakeResponses.ContainsKey(request.RequestUri))
            {
                var fakeResponse = _fakeResponses[request.RequestUri];
                return DownloadStringAsync(fakeResponse);
            }

            // Alternatively, you might want to throw here if a request comes 
            // in that is not in the _fakeResponses dictionary.
            return DownloadStringAsync(new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request });
        }

        private IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> DownloadStringAsync(HttpResponseMessage message)
        {
            return AsyncInfo.Run(delegate (CancellationToken cancellationToken, IProgress<HttpProgress> progress)
            {
                progress.Report(new HttpProgress());

                try
                {
                    return Task.FromResult(message);
                }
                finally
                {
                    progress.Report(new HttpProgress());
                }

            });
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM