Skip to content
Pure Krome edited this page Apr 3, 2015 · 4 revisions

Multiple endpoints

What: faking a multiple request endpoints

Why: unit testing a service that makes multiple requests to multiple endpoints.

How: Create a fake response for each endpoint the method calls.
NOTE: once an HttpMessageHandler is executed/used, it gets disposed. Therefore, we setup the message handler to not dispose of, after being used

public class MyService : IMyService
{
    private readonly FakeHttpMessageHandler _messageHandler;

    public MyService(FakeHttpMessageHandler messageHandler = null)
    {
        _messageHandler = messageHandler;
    }

    public async Task<Foo> GetSomeDataAsync()
    {
        var foo = await GetSomeFooDataAsync();
        foo.Baa = await GetSomeBaaDataAsync();
        
        return foo;
    }

    private async Task<Foo> GetSomeFooDataAsync()
    {
        HttpResponseMessage message;
        string content;
        using (var httpClient = _messageHandler == null
            ? HttpClientFactory.GetHttpClient("someKey", false)
            : HttpClientFactory.GetHttpClient(_messageHandler, false)) // <-- Note the `false` property == do NOT dispose.
        {
            message = await httpClient.GetAsync("http://www.something.com/some/website");
            content = await message.Content.ReadAsStringAsync();
        }
        
        if (message.StatusCode != HttpStatusCode.OK)
        { 
            // TODO: handle this ru-roh-error.
        }
        
        // Assumption: content is in a json format.
        return JsonConvert.DeserializeObject<Foo>(content);
    }
    
    private async Task<Baa> GetSomeBaaDataAsync()
    {
        HttpResponseMessage message;
        string content;
       using (var httpClient = _messageHandler == null
            ? HttpClientFactory.GetHttpClient("someKey", false)
            : HttpClientFactory.GetHttpClient(_messageHandler, false)) // <-- Note the `false` property == do NOT dispose.
        {
            // NOTE: notice how this request endpoint is different to the one, above?
            message = await httpClient.GetAsync("http://www.something.com/another/site");
            content = await message.Content.ReadAsStringAsync();
        }
        
        if (message.StatusCode != HttpStatusCode.OK)
        { 
            // TODO: handle this ru-roh-error.
        }
        
        // Assumption: content is in a json format.
        return JsonConvert.DeserializeObject<Baa>(content);
    }
}

// ... and a unit test ...


[Fact]
public async Task GivenSomeValidHttpRequests_GetSomeDataAsync_ReturnsAFoo()
{
    // Arrange.
    const string requestUrl1 = "http://www.something.com/some/website";
    const string responseData1 = "I am not some Html.";
    
    // 1. First fake response.
    var messageResponse1 = FakeHttpMessageHandler.GetStringHttpResponseMessage(responseData1);

    const string requestUrl2 = "http://www.something.com/another/site";
    const string responseData2 = "Html, I am not.";
    
    // 2. Second fake response.
    var messageResponse2 = FakeHttpMessageHandler.GetStringHttpResponseMessage(responseData2);

    var messageResponses = new Dictionary<string, HttpResponseMessage>
    {
        {requestUrl1, messageResponse1},
        {requestUrl2, messageResponse2}
    };

    // 3. Wire up the Factory to return these fake responses if those urls are attempted.
    var messageHandler = new FakeHttpMessageHandler(messageResponses);

    var myService = new MyService(messageHandler);

    // Act.
    // NOTE: network traffic will not leave your computer because you've faked the response, above.
    var result = myService.GetSomeDataAsync();
    
    // Assert.
    result.Id.ShouldBe(69);
}
Clone this wiki locally