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、expctationsを設定し、呼び出されることを確認するなど、必要なものは何でもできます。

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

私が提案するアプローチの1つは、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();
    }

2つのCreate関数の理由は、文字列Create(string)を渡したいためであり、IWebRequestCreateにはCreate(Uri)が必要です。

標準の依存関係インジェクションはIWebRequestCreateでは機能しないため編集されました。標準パターンは、インターフェイスを使用してオブジェクトをインスタンス化し、コンストラクターを介して渡します。WebRequestはコンストラクターで作成できず、インターフェースをインスタンス化できないため、上記のロジックはそれを回避します。

于 2013-03-08T02:32:11.413 に答える