使用Moq将参数修改为stubbed void方法

时间:2012-02-14 17:48:32

标签: c# moq void

我有一场完美的风暴让我无法测试课程。该类是RestClient包裹内部HttpClient(我无法修改)。 ExecuteMethod上的HttpClient方法无效。它接受IHttpMethod,并根据服务器的响应修改此对象。我想嘲笑ExecuteMethod,以便它为我修改IHttpMethod。我正在尝试使用Callback来实现这一点,但它无效。

以下是发送请求的代码:

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 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);

当执行modifyHttpMethod动作时,我会观察到两件事,我期望这两件事:

  1. 传入的IHttpMethodm)具有我希望它拥有的属性。
  2. 将模拟对象分配给m后,它包含我在测试中设置的存根值。
  3. 但是,在执行回调并将控制权返回给我的应用程序代码之后,我的method变量仍然具有我在上面的步骤1中看到的旧值,这会在尝试读取{时导致空引用异常{1}}。

    我正在尝试做甚至可以实现的目标?如果是这样,怎么样?谢谢!

1 个答案:

答案 0 :(得分:2)

我已经将你的设置复制到了模拟中,并且找不到任何问题:

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));
    }

}

该测试通过,意味着内存流不为空(否则将生成异常)。我能看到的唯一X因子是你的AsString()扩展方法(我假设这是一个扩展方法,因为intellisense没有在MemoryStream上向我展示)。你的问题可以在那里吗?

顺便说一句,你想要做的事几乎可以用Moq实现。