繁体   English   中英

可以强制C#Facebook SDK使用HTTP而不是HTTPS?

[英]Possible to force the C# Facebook SDK to use HTTP instead of HTTPS?

我需要做一些连接模拟,看看我的代码处理Facebook的各种连接错误。 我希望能够模拟500秒,超时等。

最简单的方法是使用Fiddler,但似乎不能使用HTTPS(我尝试时会得到403s)。

是否可以强制SDK使用HTTP而不是HTTPS来进行调试?

Facebook C#SDK支持您模拟整个HttpWebRequest和HttpWebResponse的场景。 事实上,我们实际上在单元测试中使用它,以便Facebook C#SDK中的每一行代码实际执行并且结果始终相同。 自动分享到:然后将这些测试迁移到v6。

对于v5,您需要覆盖FacebookClient中受保护的CreateHttpWebRequest方法。

以下是没有互联网连接时v5的示例。 有三个隐藏类HttpWebRequestWrapper,HttpWebResponseWrapper和WebExceptionWrapper,您将需要使用它们。

    public static void NoInternetConnection(this Mock<Facebook.FacebookClient> facebookClient, out Mock<HttpWebRequestWrapper> mockRequest, out Mock<WebExceptionWrapper> mockWebException)
    {
        mockRequest = new Mock<HttpWebRequestWrapper>();
        mockWebException = new Mock<WebExceptionWrapper>();
        var mockAsyncResult = new Mock<IAsyncResult>();

        var request = mockRequest.Object;
        var webException = mockWebException.Object;
        var asyncResult = mockAsyncResult.Object;

        mockRequest.SetupProperty(r => r.Method);
        mockRequest.SetupProperty(r => r.ContentType);
        mockRequest.SetupProperty(r => r.ContentLength);
        mockAsyncResult
            .Setup(ar => ar.AsyncWaitHandle)
            .Returns((ManualResetEvent)null);

        mockWebException
            .Setup(e => e.GetResponse())
            .Returns<HttpWebResponseWrapper>(null);

        mockRequest
            .Setup(r => r.GetResponse())
            .Throws(webException);

        mockRequest
            .Setup(r => r.EndGetResponse(It.IsAny<IAsyncResult>()))
            .Throws(webException);

        AsyncCallback callback = null;

        mockRequest
            .Setup(r => r.BeginGetResponse(It.IsAny<AsyncCallback>(), It.IsAny<object>()))
            .Callback<AsyncCallback, object>((c, s) =>
                                                 {
                                                     callback = c;
                                                 })
            .Returns(() =>
                         {
                             callback(asyncResult);
                             return asyncResult;
                         });

        var mockRequestCopy = mockRequest;
        var mockWebExceptionCopy = mockWebException;

        facebookClient.Protected()
            .Setup<HttpWebRequestWrapper>("CreateHttpWebRequest", ItExpr.IsAny<Uri>())
            .Callback<Uri>(uri =>
                               {
                                   mockRequestCopy.Setup(r => r.RequestUri).Returns(uri);
                                   mockWebExceptionCopy.Setup(e => e.Message).Returns(string.Format("The remote name could not be resolved: '{0}'", uri.Host));
                               })
            .Returns(request);
    }

然后,您可以按如下方式编写测试。

    [Fact]
    public void SyncWhenThereIsNotInternetConnectionAndFiddlerIsNotOpen_ThrowsWebExceptionWrapper()
    {
        var mockFb = new Mock<FacebookClient> { CallBase = true };
        Mock<HttpWebRequestWrapper> mockRequest;
        Mock<WebExceptionWrapper> mockWebException;

        mockFb.NoInternetConnection(out mockRequest, out mockWebException);

        Exception exception = null;

        try
        {
            var fb = mockFb.Object;
            fb.Get(_parameters);
        }
        catch (Exception ex)
        {
            exception = ex;
        }

        mockFb.VerifyCreateHttpWebRequest(Times.Once());
        mockRequest.VerifyGetResponse();
        mockWebException.VerifyGetReponse();

        Assert.IsAssignableFrom<WebExceptionWrapper>(exception);
    }

在v6中,我们更容易模拟HttpWebRequest和HttpWebResponse。

通过继承HttpWebRequestWrapperHttpWebReponseWrapper创建自定义HttpWebRequestWrapperHttpWebReponseWrapper

然后更改Facebook C#SDK的默认http Web请求工厂。 以下是默认工厂的示例。

FacebookClient.SetDefaultHttpWebRequestFactory(uri => new HttpWebRequestWrapper((HttpWebRequest)WebRequest.Create(uri)));

如果要根据FacebookClient实例更改HttpWebRequestFactor,请使用以下代码。

var fb = new FacebookClient();
fb.HttpWebRequestFactory = uri=> new MyHttpWebRequestWrapper(uri); 

注意:HttpWebRequestWrapper,HttpWebResponseWrapper,WebExceptionWrapper,FacebookClient.SetDefaultHttpWebRequestFactory和FacebookClient.HttpWebRequestFactory具有属性[EditorBrowsable(EditorBrowsableState.Never)]因此您可能无法在intellisense中看到它。

你提到的没有互联网连接的事实上应该是facebook c#sdk测试的一部分,而不是你的应用单元测试。 sdk应该保证,当没有互联网连接时,它总是抛出WebExceptionWrapper,你的应用程序单元测试实际上应该处理WebExceptionWrapper异常而不是模拟整个httpwebrequest和httpwebresponse。

我建议你为你的代码和代码引入另一层抽象,而不是实现。 例如。

public interface IFacebookClient {
  IEnumerable<Friend> GetFriends();
}

public class HttpsClient : IFacebookClient {
  public IEnumerable<Friend> GetFriends() {
    // Make a call out to the Facebook API, as per usual
  };
}

在您的消费代码中,您可以执行类似的操作;

public class ConsumingCode {
  private IFacebookClient _client;

  public ConsumingCode(IFacebookClient client) {
    _client = client;

    foreach (Friend friend in _client.GetFriends()) {
      // Do something with each Friend
    }
  }
}

如果您正在使用IoC容器,则可以自动为您连接。 像Caliburn.Micro这样的MVVM框架也倾向于支持这一点。

然后,当涉及单元测试(或手动测试)时,您可以更改接口的实现;

public class Http403Client : IFacebookClient {
  public IEnumerable<Friend> GetFriends() {
    throw new HttpException(403, "Forbidden");
  }
}

显然这只是一个模拟示例,但我认为它演示了您想要实现的概念。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM