C# 使用Moq将参数修改为存根void方法
我有一个完美的风暴阻止我测试一个类。该类是一个C# 使用Moq将参数修改为存根void方法,c#,moq,void,C#,Moq,Void,我有一个完美的风暴阻止我测试一个类。该类是一个RestClient,它正在包装一个内部HttpClient(我无法修改)。HttpClient上的ExecuteMethod方法无效。它接受IHttpMethod,并根据服务器的响应修改此对象。我想模拟ExecuteMethod,以便它为我修改IHttpMethod。我试图使用回调来实现这一点,但它不起作用 以下是发送请求的代码: var httpClient = this.httpClientFactory.CreateHttpClient();
RestClient
,它正在包装一个内部HttpClient
(我无法修改)。HttpClient
上的ExecuteMethod
方法无效。它接受IHttpMethod
,并根据服务器的响应修改此对象。我想模拟ExecuteMethod
,以便它为我修改IHttpMethod
。我试图使用回调
来实现这一点,但它不起作用
以下是发送请求的代码:
var httpClient = this.httpClientFactory.CreateHttpClient();
httpClient.ExecuteMethod(method);
var response = this.GetResourceResponse<T>(method.ResponseBodyAsStream.AsString());
response.ResponseHeaders = method.ResponseHeaders;
response.Status = method.StatusCode.ToString();
response.StatusCode = (int)method.StatusCode;
return response;
var httpClient=this.httpClientFactory.CreateHttpClient();
httpClient.ExecuteMethod(方法);
var response=this.GetResourceResponse(method.ResponseBodyAsStream.AsString());
response.ResponseHeaders=方法.ResponseHeaders;
response.Status=method.StatusCode.ToString();
response.StatusCode=(int)method.StatusCode;
返回响应;
下面是我对嘲弄的尝试:
var mockHttpMethod = new Mock<IHttpMethod>();
mockHttpMethod.Setup(m => m.ResponseBodyAsStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes("foo")));
var modifyHttpMethod = new Action<IHttpMethod>(m =>
{
m = mockHttpMethod.Object;
});
var mockHttpClient = new Mock<IHttpClient>();
mockHttpClient.Setup(c => c.ExecuteMethod(It.IsAny<IHttpMethod>()))
.Callback<IHttpMethod>(modifyHttpMethod);
var mockHttpClientFactory = new Mock<ILegalHoldHttpClientFactory>();
mockHttpClientFactory.Setup(f => f.CreateHttpClient()).Returns(mockHttpClient.Object);
var restClient = new RestClient(mockHttpClientFactory.Object);
var mockHttpMethod=new Mock();
mockHttpMethod.Setup(m=>m.ResponseBodyAsStream).Returns(newmemoryStream(Encoding.UTF8.GetBytes(“foo”));
var modifyHttpMethod=新操作(m=>
{
m=mockHttpMethod.Object;
});
var mockHttpClient=new Mock();
mockHttpClient.Setup(c=>c.ExecuteMethod(It.IsAny()))
.回调(modifyHttpMethod);
var mockHttpClientFactory=new Mock();
mockHttpClientFactory.Setup(f=>f.CreateHttpClient()).Returns(mockHttpClient.Object);
var restClient=new restClient(mockHttpClientFactory.Object);
当执行modifyHttpMethod
操作时,我观察到两件事,这两件事我都预料到:
IHttpMethod
(m
)具有我期望的属性m
后,它包含我在测试中设置的存根值方法
变量仍然具有我在上面步骤1中看到的旧值,这会在尝试读取方法.ResponseBodyAsStream
时导致空引用异常
我想做的事情是可以实现的吗?如果是,怎么做?谢谢 我已通过vis mocking复制了您的设置,但找不到任何问题:
public interface IHttpMethod
{
MemoryStream ResponseBodyAsStream { get; set; }
}
public interface IHttpClient
{
void ExecuteMethod(IHttpMethod method);
}
public class HttpClient : IHttpClient
{
#region IHttpClient Members
public void ExecuteMethod(IHttpMethod method)
{
}
#endregion
}
public class Factory
{
public virtual IHttpClient CreateHttpClient()
{
return new HttpClient();
}
}
public class ClassUnderTest
{
private readonly Factory _factory;
public ClassUnderTest(Factory factory)
{
_factory = factory;
}
public string GetResponseAsString(IHttpMethod method)
{
var myClient = _factory.CreateHttpClient();
myClient.ExecuteMethod(method);
return method.ResponseBodyAsStream.ToString();
}
}
[TestClass]
public class ScratchPadTest
{
[TestMethod]
public void SampleTest()
{
var mockHttpMethod = new Mock<IHttpMethod>();
mockHttpMethod.Setup(x => x.ResponseBodyAsStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes("foo")));
var modifyHttpMethod = new Action<IHttpMethod>(m =>
{
m = mockHttpMethod.Object;
});
var mockHttpClient = new Mock<IHttpClient>();
mockHttpClient.Setup(c => c.ExecuteMethod(It.IsAny<IHttpMethod>())).Callback<IHttpMethod>(modifyHttpMethod);
var myFactoryStub = new Mock<Factory>();
myFactoryStub.Setup(f => f.CreateHttpClient()).Returns(mockHttpClient.Object);
var myCut = new ClassUnderTest(myFactoryStub.Object);
Assert.IsNotNull(myCut.GetResponseAsString(mockHttpMethod.Object));
}
}
公共接口IHttpMethod
{
MemoryStream ResponseByAsStream{get;set;}
}
公共接口IHttpClient
{
无效执行方法(IHTTP方法);
}
公共类HttpClient:IHttpClient
{
#地区IHTTP客户成员
public void ExecuteMethod(IHTTP方法)
{
}
#端区
}
公营工厂
{
公共虚拟IHttpClient CreateHttpClient()
{
返回新的HttpClient();
}
}
公共类未测试
{
私有只读工厂_工厂;
公共类未测试(工厂)
{
_工厂=工厂;
}
公共字符串GetResponseAsString(IHttpMethod方法)
{
var myClient=_factory.CreateHttpClient();
myClient.ExecuteMethod(方法);
返回方法.ResponseBodyAsStream.ToString();
}
}
[测试类]
公共类测试
{
[测试方法]
公共无效样本测试()
{
var mockHttpMethod=new Mock();
mockHttpMethod.Setup(x=>x.ResponseBodyAsStream).Returns(newmemoryStream(Encoding.UTF8.GetBytes(“foo”));
var modifyHttpMethod=新操作(m=>
{
m=mockHttpMethod.Object;
});
var mockHttpClient=new Mock();
mockHttpClient.Setup(c=>c.ExecuteMethod(It.IsAny()).Callback(modifyHttpMethod);
var myFactoryStub=new Mock();
myFactoryStub.Setup(f=>f.CreateHttpClient()).Returns(mockHttpClient.Object);
var myCut=newclassundertest(myFactoryStub.Object);
IsNotNull(myCut.GetResponseAsString(mockHttpMethod.Object));
}
}
该测试通过,这意味着内存流不为null(否则将生成异常)。我能看到的唯一一个X因素是您的AsString()扩展方法(我假设这是一个扩展方法,因为intellisense没有在MemoryStream上向我显示它)。你的问题可能在那里吗
而且,顺便说一句,您尝试的方法几乎肯定可以通过最小起订量实现。我认为问题不在于扩展方法。我可以看到扩展方法如何读取流并将其关闭,从而使其不可用,但在执行AsString()方法之前,流实际上不可用。我不知道为什么你的代码有效而我的代码无效。最后我做了一些重构,使它更易于测试,所以这不再是一个问题,但我仍然希望它能够工作,因为它似乎是一种有用的技术。非常感谢您的回复。没问题——如果您有一个更易于测试的方法,那总是很好的。:)不过,我想说的是,我非常肯定,你可以通过Moq或其他方式实现你想要的。有时要达到目的并不容易,但它相当灵活。