때문에 HttpClient
사용 SendAsync
방법을 모두 수행하려면 HTTP Requests
, 당신은 할 수있는 override SendAsync
방법과 조롱HttpClient
.
랩을 작성 HttpClient
하려면 interface
아래와 같이
public interface IServiceHelper
{
HttpClient GetClient();
}
그런 다음 위 interface
의 서비스에서 종속성 주입에 사용하십시오. 아래 샘플
public class SampleService
{
private readonly IServiceHelper serviceHelper;
public SampleService(IServiceHelper serviceHelper)
{
this.serviceHelper = serviceHelper;
}
public async Task<HttpResponseMessage> Get(int dummyParam)
{
try
{
var dummyUrl = "http://www.dummyurl.com/api/controller/" + dummyParam;
var client = serviceHelper.GetClient();
HttpResponseMessage response = await client.GetAsync(dummyUrl);
return response;
}
catch (Exception)
{
// log.
throw;
}
}
}
이제 단위 테스트 프로젝트에서 조롱을위한 도우미 클래스를 만듭니다 SendAsync
. 여기 에 메서드 를 재정의하는 옵션을 제공하는 FakeHttpResponseHandler
클래스 inheriting
DelegatingHandler
가 있습니다 SendAsync
. SendAsync
메서드를 재정의 한 후 메서드를 HTTP Request
호출 SendAsync
하는 각각에 대한 응답을 설정해야합니다. 이를 위해 Dictionary
with key
as Uri
및 value
as 를 생성하여 a HttpResponseMessage
가있을 때마다 일치 하는 HTTP Request
경우 구성된 .Uri
SendAsync
HttpResponseMessage
public class FakeHttpResponseHandler : DelegatingHandler
{
private readonly IDictionary<Uri, HttpResponseMessage> fakeServiceResponse;
private readonly JavaScriptSerializer javaScriptSerializer;
public FakeHttpResponseHandler()
{
fakeServiceResponse = new Dictionary<Uri, HttpResponseMessage>();
javaScriptSerializer = new JavaScriptSerializer();
}
/// <summary>
/// Used for adding fake httpResponseMessage for the httpClient operation.
/// </summary>
/// <typeparam name="TQueryStringParameter"> query string parameter </typeparam>
/// <param name="uri">Service end point URL.</param>
/// <param name="httpResponseMessage"> Response expected when the service called.</param>
public void AddFakeServiceResponse(Uri uri, HttpResponseMessage httpResponseMessage)
{
fakeServiceResponse.Remove(uri);
fakeServiceResponse.Add(uri, httpResponseMessage);
}
/// <summary>
/// Used for adding fake httpResponseMessage for the httpClient operation having query string parameter.
/// </summary>
/// <typeparam name="TQueryStringParameter"> query string parameter </typeparam>
/// <param name="uri">Service end point URL.</param>
/// <param name="httpResponseMessage"> Response expected when the service called.</param>
/// <param name="requestParameter">Query string parameter.</param>
public void AddFakeServiceResponse<TQueryStringParameter>(Uri uri, HttpResponseMessage httpResponseMessage, TQueryStringParameter requestParameter)
{
var serilizedQueryStringParameter = javaScriptSerializer.Serialize(requestParameter);
var actualUri = new Uri(string.Concat(uri, serilizedQueryStringParameter));
fakeServiceResponse.Remove(actualUri);
fakeServiceResponse.Add(actualUri, httpResponseMessage);
}
// all method in HttpClient call use SendAsync method internally so we are overriding that method here.
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if(fakeServiceResponse.ContainsKey(request.RequestUri))
{
return Task.FromResult(fakeServiceResponse[request.RequestUri]);
}
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound)
{
RequestMessage = request,
Content = new StringContent("Not matching fake found")
});
}
}
IServiceHelper
프레임 워크를 모의하거나 아래와 같이 새로운 구현을 만듭니다 . 이 FakeServiceHelper
클래스를 사용하여 FakeHttpResponseHandler
클래스 를 주입 할 수 있으므로 HttpClient
이것에 의해 생성 될 때마다 실제 구현 대신 class
사용할 수 있습니다 FakeHttpResponseHandler class
.
public class FakeServiceHelper : IServiceHelper
{
private readonly DelegatingHandler delegatingHandler;
public FakeServiceHelper(DelegatingHandler delegatingHandler)
{
this.delegatingHandler = delegatingHandler;
}
public HttpClient GetClient()
{
return new HttpClient(delegatingHandler);
}
}
그리고 테스트 FakeHttpResponseHandler class
에서 Uri
및 예상 HttpResponseMessage
. 은 Uri
실제해야 service
엔드 포인트 Uri
때 있도록 overridden SendAsync
방법은 실제에서 호출 service
구현는 일치 Uri
에 Dictionary
구성된와 응답을 HttpResponseMessage
. 구성 후 FakeHttpResponseHandler object
가짜 IServiceHelper
구현에 삽입하십시오 . 그런 다음 FakeServiceHelper class
실제 서비스 에을 주입하여 실제 서비스가 override SendAsync
메서드 를 사용하도록 합니다.
[TestClass]
public class SampleServiceTest
{
private FakeHttpResponseHandler fakeHttpResponseHandler;
[TestInitialize]
public void Initialize()
{
fakeHttpResponseHandler = new FakeHttpResponseHandler();
}
[TestMethod]
public async Task GetMethodShouldReturnFakeResponse()
{
Uri uri = new Uri("http://www.dummyurl.com/api/controller/");
const int dummyParam = 123456;
const string expectdBody = "Expected Response";
var expectedHttpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(expectdBody)
};
fakeHttpResponseHandler.AddFakeServiceResponse(uri, expectedHttpResponseMessage, dummyParam);
var fakeServiceHelper = new FakeServiceHelper(fakeHttpResponseHandler);
var sut = new SampleService(fakeServiceHelper);
var response = await sut.Get(dummyParam);
var responseBody = await response.Content.ReadAsStringAsync();
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual(expectdBody, responseBody);
}
}
GitHub Link : 샘플 구현이 있습니다.
HttpClient
인터페이스에서를 노출하는 것이 문제입니다. 클라이언트가HttpClient
구체적인 클래스 를 사용하도록 강요하고 있습니다 . 대신, 당신은 노출해야 추상화 의를HttpClient
.