我正在试图弄清楚如何使用Moq进行我的第一次模拟。我也很嘲笑。
假设我有以下TDD测试:
[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
// Arrange
var preAuthorizeRequest = new PreAuthorizeRequest();
// Act
var authorizeResponse = _dataProcessor.SendRequest(preAuthorizeRequest);
// Assert
Assert.IsNotNull(authorizeResponse);
}
上面那个测试的场景是,如果我们发送一个没有状态的对象实例,我们仍然应该找回一个响应对象(它不会爆炸)。所以我想在Mock和Stub术语中我想我想测试dataProcessor的SendRequest方法的行为,因为它会发回PreAuthorizeResponse的实例....对吗?
现在这里有关于这些类型的信息:
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;
}
所以我没有看到需要模拟,换句话说是模拟权限上的验证调用?我想我只需要一个存根并测试我是否得到了PreAuthorizeResponse的实例。所以我猜这是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));
}
答案 0 :(得分:1)
不,你真的不想嘲笑你想要测试的对象。您应该模拟该对象的依赖项(例如数据库对象)。
dataProcessor
是被测对象(也称为被测系统),其他一切都是协作者(SUT的依赖关系)。
由于SendRequest
方法中存在的硬依赖性数量很多,您将很难对此进行正确测试。
至少,您想要模拟PaymentRequestValidator
,以便在发送特定类型的请求时,您可以让模拟设置说它无效,然后在代码,这反过来会导致SendRequest
方法返回响应。
要实现这一点,您需要重构代码,以便传递请求验证器的模拟实例。此外,可能还有很多其他对象。
例如,您很可能需要模拟PaymentUtilities
对象,以便您可以使用您使用的方法返回Mock对象,这些对象本身设置为返回此测试的特定内容。类似地,ConfigurationValidator
- 它会在从测试中调用它时返回一个有效的配置(可能是一个不同的测试),或者你是否也需要模拟它?
这很好地进入了依赖注入和控制反转的领域。我不是通过提供链接来侮辱你,但是这些主题在印刷品和网络上都有很好的文献资料。
答案 1 :(得分:0)
查看代码,如果您尝试测试SendRequest
方法,似乎您不需要进行任何模拟。您需要模拟您要测试的内容的依赖关系,而不是测试对象本身。因此,如果您的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);
}