Vraag Stubbing of Mocking ASP.NET Web API HttpClient


Ik gebruik de nieuwe Web API-bits in een project en ik heb ontdekt dat ik het normale niet kan gebruiken HttpMessageRequest, omdat ik clientcertificaten aan het verzoek moet toevoegen. Als gevolg hiervan gebruik ik de HttpClient (dus ik kan gebruiken WebRequestHandler). Dit werkt allemaal goed, behalve dat het niet stomp / bespotvriendelijk is, tenminste voor Rhino Mocks.

Normaal zou ik een wrapper-service maken HttpClient die ik in plaats daarvan zou gebruiken, maar ik zou dit indien mogelijk willen vermijden, omdat er veel methoden zijn die ik zou moeten omwikkelen. Ik hoop dat ik iets mis - suggesties om te stompen HttpClient?


25
2018-05-21 23:30


oorsprong


antwoorden:


Ik gebruik Moq en ik kan de HttpClient verwijderen. Ik vind dit hetzelfde voor Rhino Mock (ik heb het zelf niet geprobeerd). Als u alleen de HttpClient wilt stompen, zou de onderstaande code moeten werken:

var stubHttpClient = new Mock<HttpClient>();
ValuesController controller = new ValuesController(stubHttpClient.Object);

Corrigeer me als ik het mis heb. Ik veronderstel dat je hier verwijst naar de leden die zich binnen HttpClient uithollen.

De meest populaire isolatie / mock-objectraamwerken laten je niet toe om te stampen / instellen op niet-virtuele leden De onderstaande code genereert bijvoorbeeld een uitzondering

stubHttpClient.Setup(x => x.BaseAddress).Returns(new Uri("some_uri");

Je hebt ook gezegd dat je liever geen wrapper wilt maken omdat je veel HttpClient-leden zou omwikkelen. Niet duidelijk waarom je veel methoden moet inpakken, maar je kunt eenvoudigweg alleen de methoden inpakken die je nodig hebt.

Bijvoorbeeld :

public interface IHttpClientWrapper  {   Uri BaseAddress { get;  }     }

public class HttpClientWrapper : IHttpClientWrapper
{
   readonly HttpClient client;

   public HttpClientWrapper()   {
       client = new HttpClient();
   }

   public Uri BaseAddress   {
       get
       {
           return client.BaseAddress;
       }
   }
}

De andere opties waarvan ik denk dat ze voor u van nut kunnen zijn (veel voorbeelden zijn er dus ik zal de code niet schrijven) Microsoft Moles Framework http://research.microsoft.com/en-us/projects/moles/ Microsoft Fakes: (als u VS2012 Ultimate gebruikt) http://msdn.microsoft.com/en-us/library/hh549175.aspx


11
2017-09-03 12:18



Als alternatief voor de uitstekende ideeën die al door @Raj zijn gepresenteerd, is het misschien mogelijk om een ​​stap lager te gaan en de HttpMessageHandler in plaats daarvan.

Als je een klas maakt die een HttpClient accepteer het als een inspanningsparameter voor afhankelijkheid in de constructor, en als je eenheidstests uitvoert, kun je dit in een HttpClient die is ingespoten met die van jezelf HttpMessageHandler. Deze eenvoudige klasse heeft maar één abstracte methode die je moet implementeren, als volgt:

public class FakeHttpMessageHandler : HttpMessageHandler
    {
    public HttpRequestMessage RequestMessage { get; private set; }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
        RequestMessage = request;
        return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
        }
    }

Mijn triviale voorbeeld redt gewoon de HttpRequestMessage in een openbare eigenschap voor latere inspectie en retourneert HTTP 200 (OK), maar u kunt dit aanvullen door een constructor toe te voegen die het resultaat instelt dat u wilt retourneren.

Je zou deze klasse als volgt gebruiken:

public void foo()
    {
    //Arrange
    var fakeHandler = new FakeHttpMessageHandler();
    var client = new HttpClient(fakeHandler);
    var SUT = new ClassUnderTest(client);

    //Act
    SUT.DomSomething();

    //Assert
    fakeHandler.RequestMessage.Method.ShouldEqual(HttpMethod.Get); // etc...
    }

Er zijn beperkingen aan deze aanpak, bijvoorbeeld in een methode die meerdere verzoeken doet of meerdere moet maken HttpClients, dan kan de nep-handler te gecompliceerd beginnen te worden. Het kan echter de moeite waard zijn om rekening te houden met eenvoudige gevallen.


59
2018-06-30 12:08



Ik heb een paar maanden geleden een bibliotheek vrijgegeven genaamd MockHttp wat handig kan zijn. Het maakt gebruik van een aangepast HttpMessageHandler met een vloeiende (en uitbreidbare) API. U kunt de Spot-handler (of HttpClient) in uw serviceklasse injecteren en deze zal reageren zoals deze was geconfigureerd.

Hieronder ziet u het basisgebruik. De When en Respond methoden hebben een heleboel overbelasting, inclusief het uitvoeren van aangepaste logica. De documentatie op de GitHub-pagina gaat in veel meer detail.

var mockHttp = new MockHttpMessageHandler();

// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localhost/api/user/*")
        .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);

var response = async client.GetAsync("http://localhost/api/user/1234");
// or without async: var response = client.GetAsync(...).Result;

var json = await response.Content.ReadAsStringAsync();

// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}

36
2017-09-22 23:53