我正在尝试对我编写的动作过滤器进行单元测试。我想模拟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[] { });
答案 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
进入可测试状态更好。