什么是测试对象与合作者

本文关键字:合作者 对象 测试 什么 | 更新日期: 2023-09-27 18:01:45

我想弄清楚如何做我的第一个模拟Moq。我也不习惯嘲笑。

假设我有以下TDD测试:

[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
    // Arrange
    var preAuthorizeRequest = new PreAuthorizeRequest();
    // Act
    var authorizeResponse = _dataProcessor.SendRequest(preAuthorizeRequest);
    // Assert
    Assert.IsNotNull(authorizeResponse);
}

上面测试的场景是,如果我们发送一个没有状态的对象实例,我们仍然应该得到一个响应对象(它不应该爆炸)。所以我猜在模拟和存根方面我猜我想测试dataProcessor的SendRequest方法的行为因为它会发回一个preauthorizerresponse ....的实例,对吧?

下面是关于这些类型的信息:

    public interface IPaymentRequest
    {
        string SecurityToken { get; set; }
        int RetailID { get; set; }
        int ProcessorId { get; set; }
    }
    public class PreAuthorizeRequest : IPaymentRequest
    {
        public string SecurityToken { get; set; }
        public int RetailID { get; set; }
        public int ProcessorId { get; set; }
        public PreAuthorizeTransaction Transaction { get; set; }
    }
       public IPaymentResponse SendRequest(IPaymentRequest request)
        {
            ITransaction transaction = PaymentUtilities.GetPaymentRequestTransactionType(request);
            IPaymentResponse response = PaymentUtilities.GetPaymentResponseType(request);
            var transactionType = PaymentUtilities.GetPaymentRequestTransactionTypeEnum(request);
            var requestValidator = new PaymentRequestValidator();
            requestValidator.ValidateRequest(request);
            var requestIsValid = requestValidator.RequestIsValid;
            if (!requestIsValid)
            {
                response = PaymentUtilities.BuildPaymentResponse(request, requestValidator, transaction, transactionType);
                return response;
            }
IAutoPaymentProcessor autoPaymentProcessor = CreateAutoPaymentProcessor(request);
            var configValidator = new ConfigurationValidator(autoPaymentProcessor);
            configValidator.ValidateConfigurationSettings();
            bool settingsAreValid = configValidator.ConfigIsValid;
            if (!settingsAreValid)
            {
                response = PaymentUtilities.BuildPaymentResponse(request, requestValidator, transaction, transactionType);
                return response;
            }
            response = SetConfigSettings(request, response);
            Document dataResponseDoc = SendRequest(request, response);
            response.PaymentProcessorId = (int)Enums.PaymentProcessorType.Data;
            response.ProviderAuthCode = dataResponseDoc != null ? dataResponseDoc.get("Response.authcode") : string.Empty;
            response.ProviderReference = dataResponseDoc != null ? dataResponseDoc.get("Response.data_reference") : string.Empty;
            return response;
        }

所以我不认为需要模拟,换句话说,对模拟进行验证调用,对吗?我想我只需要一个存根来测试我是否得到一个preauthorizerresponse的实例。所以我猜这是Moq的存根,对吧?

如果我是对的,我只需要在这里使用一个存根,那么我该如何使用Moq呢?

我试过了,但我觉得这是错误的,因为我觉得SUT是我的数据处理器,我相信你不应该在测试中模拟对象:

    [TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
    // Arrange - setup data
    var dataProcessorStub = new Mock<IPaymentProcessor>();
    var preAuthorizeRequest = new PreAuthorizeRequest();
    // Act
    //setup - expectations
    dataProcessorStub.Setup(p => p.SendRequest(It.IsAny<PreAuthorizeRequest>())).Returns(It.IsAny<PreAuthorizeResponse>());
    // excercise
    var preAuthorizeResponse = dataProcessorStub.Object.SendRequest(preAuthorizeRequest);
    // Assert
    Assert.IsInstanceOfType(preAuthorizeResponse, typeof(PreAuthorizeResponse));
}

什么是测试对象与合作者

不,您不会真的想要模拟您要测试的对象。你应该模拟该对象(例如数据库对象)的依赖关系。

dataProcessor是测试下的对象(也称为测试下的系统),其他一切都是合作者(SUT的依赖)。

你会发现很难正确地测试它,因为你在SendRequest方法中有很多硬依赖项。

至少,您希望模拟PaymentRequestValidator,以便当您发送特定类型的请求时,您可以让模拟设置说它无效,然后在代码中处理它,这反过来将导致SendRequest方法返回响应。

要实现这一点,您需要重构代码,以便传入请求验证器的模拟实例。而且,可能还有相当多的其他对象。

例如,您很可能需要模拟PaymentUtilities对象,以便您可以使用返回mock对象的方法,这些方法本身被设置为为该测试返回特定的内容。类似地,ConfigurationValidator -当它从测试(可能是不同的测试)调用时,它会返回一个有效的配置,或者您也需要模拟它吗?

这很好地进入了依赖注入控制反转的领域。我不想通过提供链接来侮辱你,但是这些主题在印刷和网络上的文献中都有很好的涵盖。

查看代码,如果您试图测试SendRequest方法,似乎不需要做任何mock。您需要模拟您要测试的对象的依赖关系,而不是测试对象本身。因此,如果您的PaymentProcessor有测试所需的任何外部依赖项,则需要模拟它们。

SendRequest方法确实接受一个可以模拟的接口,但是直接传递一个新创建的PreAuthorizeRequest更容易。

[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
    // Arrange
    var preAuthorizeRequest = new PreAuthorizeRequest();
    // Act
    var authorizeResponse = _dataProcessor.SendRequest(preAuthorizeRequest);
    // Assert
    Assert.IsNotNull(authorizeResponse);
}

或者您可以模拟请求:

 [TestMethod]
 public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
 {
     // Arrange
     var request = new Mock<IPaymentRequest>();
     // Act
     var authorizeResponse = _dataProcessor.SendRequest(request);
     // Assert
     Assert.IsNotNull(authorizeResponse);
 }