Eri*_*k T 28 unit-testing rhino-mocks wcf-web-api
我在项目中使用新的Web API位,我发现我无法正常使用HttpMessageRequest,因为我需要将客户端证书添加到请求中.结果,我正在使用HttpClient(所以我可以使用WebRequestHandler).这一切都很好,除了它不是存根/模拟友好,至少对于Rhino Mocks.
我通常会创建一个HttpClient我将使用的包装器服务,但我想尽可能避免这种情况,因为我需要包装很多方法.我希望我遗漏了一些东西 - 关于如何存根的任何建议HttpClient?
Tim*_*ong 62
作为@Raj已经提出的优秀创意的替代方案,有可能更低一步并模仿/伪造HttpMessageHandler.
如果您HttpClient在构造函数中创建任何需要接受它作为依赖注入参数的类,那么在单元测试时,您可以传入HttpClient已经注入了自己的类HttpMessageHandler.这个简单的类只有一个需要实现的抽象方法,如下所示:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我的简单示例只是保存HttpRequestMessage在公共属性中供以后检查并返回HTTP 200(OK),但您可以通过添加一个设置您想要返回的结果的构造函数来扩充它.
你会像这样使用这个类:
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...
}
Run Code Online (Sandbox Code Playgroud)
这种方法存在一些限制,例如在一个产生多个请求或需要创建多个HttpClients的方法中,那么假处理程序可能会变得太复杂.但是,对于简单的情况,可能值得考虑.
Ric*_*lay 38
几个月前我发布了一个名为MockHttp的库,它可能很有用.它使用HttpMessageHandler具有流畅(和可扩展)API 的自定义.您可以将模拟的处理程序(或HttpClient)注入到服务类中,它将在配置时进行响应.
下面显示了基本用法.该When和Respond方法有一堆重载,包括运行自定义逻辑的.在GitHub的页面文件进入到更多细节.
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'}
Run Code Online (Sandbox Code Playgroud)
Spo*_*ock 11
我使用Moq,我可以删除HttpClient.我认为这对于Rhino Mock来说是一样的(我没有亲自尝试过).如果你只想存根HttpClient,下面的代码应该可以工作:
var stubHttpClient = new Mock<HttpClient>();
ValuesController controller = new ValuesController(stubHttpClient.Object);
Run Code Online (Sandbox Code Playgroud)
如果我错了,请纠正我.我想你在这里指的是在HttpClient中删除成员.
最流行的隔离/模拟对象框架将不允许您在非虚拟成员上存根/设置例如以下代码引发异常
stubHttpClient.Setup(x => x.BaseAddress).Returns(new Uri("some_uri");
Run Code Online (Sandbox Code Playgroud)
您还提到过,您希望避免创建包装器,因为您将包装许多HttpClient成员.不清楚为什么你需要包装很多方法,但你可以轻松地只包装你需要的方法.
例如 :
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为其他选项可能会对您有所帮助(有很多例子,所以我不会编写代码)Microsoft Moles Framework http://research.microsoft.com/en-us/projects/moles/ Microsoft Fakes :(如果您使用的是VS2012 Ultimate) http://msdn.microsoft.com/en-us/library/hh549175.aspx