4

我想测试一个通过 Webrequest 发送文本的类,如何使用 Moq 模拟 GetRequest 方法来测试 GetRequest?

public class Sender

public void Send(string Message)
{
...
WebRequest myReq = GetRequest(sParmeter);
}

protected WebRequest GetRequest(string URl)
        {
            return WebRequest.Create(URl);
        }
}
4

3 回答 3

4

对于这样的事情,简单的方法是将您的WebRequest实例及其操作移动到接口中介后面。

例子:

public interface IWebRequestHandler
{
WebRequest GetRequest (string URI);
}

public class WebRequestHandler : IWebRequestHandler
{
public WebRequest GetRequest (string URI)
{
return WebRequest.Create(URl);
}
} 

你的发件人类应该有一个可注入的实例,IWebRequestHandler你可以用 模拟它MOQ,设置预期,验证它被调用以及你可能想要的任何其他东西。

public class Sender
{
public IWebRequestHandler Handler{get;set;}
public void Send(string Message)
{
Handler.GetRequest(new URI(Message));//call the method with right params, just an example
}
}
于 2012-06-14T01:03:35.733 回答
3

我要建议的方法之一与 AD.Net 的响应相同,但如果您不想修改现有结构并仍然进行测试,您可以执行以下操作:

修改你原来的类如下:

public class Sender
{
    public void Send(string Message)
    {
    ...
        WebRequest myReq = GetRequest(sParmeter);
    }

    protected virtual WebRequest GetRequest(string URl)
    {
        return WebRequest.Create(URl);
    }
}

并在您的测试项目中扩展此类,如下所示:

public class MockSender: Sender
{
    private WebRequest _response;
    public MockSender(WebRequest response)
    {
    _response=response;       //initialize data to be returned
    }
    protected override WebRequest GetRequest(string URl)
    {
        //return your test;
    }
}

现在在您的测试中创建一个 MockSender 类型的实例并在其上调用 Send 方法。

Moq 期望您的类是抽象的,或者您实现一个接口,从而模拟 AD.Net 所描述的接口

希望这可以帮助..

于 2012-06-14T05:28:54.490 回答
2

另一种方法是将 IWebRequestCreate 方法传递给构造函数。

    public HTTPRequestFactory(IWebRequestCreate create)
    {
        _IWebRequestCreate = create;

    }

    public HTTPRequestFactory()
    {
        //Do nothing this is the real constructor, above is just for testing.
    }

    public WebRequest Create(String uri)
    {
        Uri _uri = new Uri("http://"+this.address+uri);
        request =  (HttpWebRequest)this.Create(_uri);
        return request;
    }

    public WebRequest  Create(Uri uri)
        if (null == _IWebRequestCreate)
        {
            //use the real one
            request = WebRequest.Create(uri);
        }
        else
        {
            //testing so use test one
            request = _IWebRequestCreate.Create(uri);
        }
        return request;
    }

然后,您可以使用标准测试来确认它是否按您的意愿被调用。

        [Test]
    public void NewwebrequestCreatesWebRequest()
    {
        var mockCreate = new Mock<IWebRequestCreate>();
        mockCreate.Setup(x => x.Create(It.IsAny<Uri>()));
        HTTPRequestFactory webrequest = new HTTPRequestFactory(mockCreate.Object);
        HttpWebRequest request = (HttpWebRequest)webrequest.Create(testURI);
        mockCreate.VerifyAll();       
    }

    [Test]
    public void webrequestUsesAddressProperty()
    {
        var mockCreate = new Mock<IWebRequestCreate>();
        string IP = "10.99.99.99";
        Uri expected = new Uri("http://10.99.99.99/services");
        mockCreate.Setup(x => x.Create(expected));
        HTTPRequestFactory webrequest = new HTTPRequestFactory(mockCreate.Object);
        webrequest.address = IP;
        HttpWebRequest request = (HttpWebRequest)webrequest.Create(testURI);
        mockCreate.VerifyAll();
    }

使用两个 Create 函数的原因是您要传入一个字符串 Create(string),而 IWebRequestCreate 需要一个 Create(Uri)。

已编辑,因为标准依赖注入不适用于 IWebRequestCreate。标准模式是使用接口实例化一个对象并通过构造函数将其传入。由于无法使用构造函数创建 WebRequest 并且无法实例化接口,因此上述逻辑可以解决此问题。

于 2013-03-08T02:32:11.413 回答