什么是测试对象与合作者
本文关键字:合作者 对象 测试 什么 | 更新日期: 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);
}