Как издеваться над HttpClientCertificate? - PullRequest
4 голосов
/ 03 сентября 2010

Я пытаюсь провести модульное тестирование фильтра действий, который я написал. Я хочу издеваться над 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 ]

2 голосов
/ 24 сентября 2010

Это самый неловкий случай создания тестируемых систем в .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).Таким образом, вы создаете тестовую поверхность для подключения фиктивных объектов.

1 голос
/ 27 сентября 2010

Если вы не хотите писать больше кода для создания класса "Testable", я предлагаю вам использовать Typemock Isolator , если не указано иное, он ищет первый доступный c'tor - публичный, внутренний или приватный и поддельный(насмешливо) это параметры, так что вам не придется.

Создать поддельный объект так же просто, как:

var fakeHttpClientCertificate = Isolate.Fake.Instance<HttpClientCertificate>();
1 голос
/ 23 сентября 2010

Проблема в том, что вам нужно указывать параметры конструктора при создании макета HttpClientCertificate.

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

Плохая новость заключается в том, что ctor для HttpClientCertificate является внутренним и принимает HttpContext, поэтому он, вероятно, не будет работать.

0 голосов
/ 27 сентября 2010

Другой альтернативой является использование бесплатной платформы Microsoft Moles .Это позволит вам заменить любой метод .NET своим собственным делегатом.Проверьте ссылку, поскольку она дает пример, который довольно легко понять.Я думаю, вам будет гораздо приятнее, чем добавлять слои косвенности, чтобы HttpClientCertificate перешел в тестируемое состояние.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...