Это самый неловкий случай создания тестируемых систем в .NET.Я неизменно заканчиваю тем, что добавляю слой абстракции над компонентом, который я не могу высмеять.Обычно это требуется для классов с недоступными конструкторами (как в этом случае), не виртуальными методами или методами расширения.
Вот шаблон, который я использую (который я считаю Шаблон адаптера ) ианалогично тому, что команда 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)
.Таким образом, вы создаете тестовую поверхность для подключения фиктивных объектов.