Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Moq将参数修改为存根void方法_C#_Moq_Void - Fatal编程技术网

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或其他方式实现你想要的。有时要达到目的并不容易,但它相当灵活。