如何模拟HttpClientCertificate?

时间:2010-09-03 08:51:05

标签: unit-testing mocking moq

我正在尝试对我编写的动作过滤器进行单元测试。我想模拟HttpClientCertificate,但是当我使用MOQ时,我得到了异常。 HttpClientCertificate没有公共默认构造函数。

代码:

//Stub HttpClientCertificate </br>
var certMock = new Mock<HttpClientCertificate>();
HttpClientCertificate clientCertificate = certMock.Object;
requestMock.Setup(b => b.ClientCertificate).Returns(clientCertificate);
certMock.Setup(b => b.Certificate).Returns(new Byte[] { });

4 个答案:

答案 0 :(得分:2)

这是在.NET中创建单元可测试系统的最尴尬的案例。我不变的最终在组件上添加了一层抽象,我无法模仿。通常,对于具有不可访问的构造函数(如本例),非虚方法或扩展方法的类,这是必需的。

这是我使用的模式(我认为是Adapter pattern),类似于MVC团队对所有RequestBase / ResponseBase类所做的操作,使它们可以单元测试。

//Here is the original HttpClientCertificate class
//Not actual class, rather generated from metadata in Visual Studio

public class HttpClientCertificate : NameValueCollection {
    public byte[] BinaryIssuer { get; }
    public int CertEncoding { get; }
    //other methods
    //...
}

public class HttpClientCertificateBase {
    private HttpClientCertificate m_cert;

    public HttpClientCertificateBase(HttpClientCertificate cert) {
       m_cert = cert;
    }
    public virtual byte[] BinaryIssuer { get{return m_cert.BinaryIssuer;} }
    public virtual int CertEncoding { get{return m_cert.CertEncoding;} }
    //other methods
    //...
}

public class TestClass {
  [TestMethod]
  public void Test() {
      //we can pass null as constructor argument, since the mocked class will never use it and mock methods will be called instead
      var certMock = new Mock<HttpClientCertificate>(null);
      certMock.Setup(cert=>cert.BinaryIssuer).Returns(new byte[1]);
  }
}

在使用HttpClientCertificate的代码中,您改为使用HttpClientCertificateBase,您可以像这样实例化new HttpClientCertificateBase(httpClientCertificateInstance)。这样您就可以创建一个测试表面来插入模拟对象。

答案 1 :(得分:1)

问题是您在创建HttpClientCertificate的模拟时需要指定构造函数参数。

var certMock = new Mock<HttpClientCertificate>(ctorArgument);

坏消息是HttpClientCertificate的ctor是内部的并且接受了HttpContext,所以它可能不起作用。

答案 2 :(得分:1)

除非您想编写更多代码以使类“可测试”,否则我建议您使用Typemock Isolator,除非另有说明,否则它会查找可用的第一个cid:public,internal或private和fake(mocks)这是参数所以你不必这么做。

创建假对象非常简单:

var fakeHttpClientCertificate = Isolate.Fake.Instance<HttpClientCertificate>();

答案 3 :(得分:0)

另一种选择是使用free Microsoft Moles framework。它允许您用自己的委托替换任何.NET方法。查看链接,因为它提供了一个非常容易理解的示例。我认为你会发现它比添加间接层以使HttpClientCertificate进入可测试状态更好。