简体   繁体   English

对依赖于httpclient响应的服务类进行单元测试

[英]Unit testing a service class with dependency on httpclient response

I have a service-class that gets a FlurlHttpClient injected in the constructor. 我有一个服务类,它在构造函数中注入了FlurlHttpClient

It has a public method which makes a call using the httpClient and then parses the response and returns a class. 它具有一个公共方法,该方法使用httpClient进行调用,然后解析响应并返回一个类。 So basically I want to fake the response from the API and test the parse-method, which is private. 因此,基本上我想伪造API的响应并测试私有的parse-method。

How do I unit test this? 如何对此进行单元测试? I am using NUnit and FakeItEasy for testing. 我正在使用NUnit和FakeItEasy进行测试。 So far I got this, but how do I ensure that the ParseResult -method gets tested with the faked result from the API? 到目前为止,我已经知道了,但是如何确保使用来自API的伪造结果测试ParseResult方法?

Code so far: 到目前为止的代码:

Unit-test: 单元测试:

[Test]
public void GetShipmentData_SuccessfullTracking_ReturnsValidEntity() {
  //Fake the service-class
  var sut = A.Fake<IApiClient>();
  using (var httpTest = new HttpTest()) {
    httpTest.RespondWithJson(GetJsonFromFile("../../../Assets/SuccessfullApiTrackingResponse.json"), 200);

    //This does not actually run the function on the service-class.
    var response = sut.TrackShipmentUsingReferenceNumber("fakeReferenceNumber");

    Assert.IsTrue(response.SuccessfullShipmentTracking);
    Assert.IsNotNull(response.ApiResponseActivity);
  }
}

Api-class: api类:

public class ApiClient : IApiClient {

    readonly ILogger _logger;
    private readonly IFlurlClient _httpClient;

    public ApiClient(IFlurlClientFactory flurlClientFac) {
      _httpClient = flurlClientFac.Get(ApiClientConfiguration.BaseAdress);
    }

    public ApiResponse TrackShipmentUsingReferenceNumber(string referenceNumber) {
      var request = GenerateApiRequestUsingReferenceNumber(referenceNumber);
      var response = _httpClient.Request("Track").PostJsonAsync(request).ReceiveString();

      return ParseResult(response.Result);
    }

    private ApiResponse ParseResult(string input) {
        //Shortened
      return = JObject.Parse<ApiResponse>(input);
    }
}

@Philippe already provided a good answer ( even if it's just a comment ... ), this is meant to be an alternative. @Philippe已经提供了一个很好的答案(即使只是一个评论……),这也可以作为一种选择。

This is one of those cases where I would not want to mock anything. 这是我不想模拟任何东西的情况之一。 What you want to test is the private method which takes as input a string. 您要测试的是私有方法,该方法将字符串作为输入。

Imagine how easy it was if : 想象一下,如果有那么容易:

A. the method was public instead, all you'd have to do is literally call it with whatever input you wanted. 答:该方法是公共的,您要做的就是从字面上使用您想要的任何输入来调用它。 Easy, no mocking. 简单,没有嘲笑。

B. Assuming it does way more than just what you shared, you could take it out of this class entirely into its own class which only deals with parsing a result and again, it would be trivial to test without mocking. B.假设它所做的不仅是您共享的内容,您可以将其从此类中完全带入其自己的类,该类仅处理解析结果,并且再次进行测试而无需模拟就很简单了。

This would be a functional way of coding and it makes testing so much easier. 这将是一种实用的编码方式,并且使测试变得更加容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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