我有一个接口定义,其中方法定义了out参数
public interface IRestCommunicationService
{
TResult PerformPost<TResult, TData>(string url, TData dataToSend, out StandardErrorResult errors);
}
我有以下使用上述界面的类
public TripCreateDispatchService(IRestCommunicationAuthService restCommunicationService, ISettings settings)
{
_restCommunicationService = restCommunicationService;
_settings = settings;
}
public FlightAlert CreateTrip(string consumerNumber, PostAlertModel tripModel, out StandardErrorResult apiErrors)
{
url = .. code ommited
var result = _restCommunicationService.PerformPost<FlightAlert, PostAlertModel>(url), tripModel, out apiErrors);
return result;
}
在我的单元测试中,我试图验证是否调用了RestCommunication对象的PerformPost方法。
但无论我做什么,我都无法让Moq验证方法是否被调用
public void DispatchService_PerformPost()
{
var consumerNumber = ...
var trip = ...
var result = ...
var apiErrors = new StandardErrorResult();
... code to setup mock data
_mockRestCommunicationService = new Mock<IRestCommunicationAuthService>();
_mockEestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors)).Verifiable();
_systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
_mockRestCommunicationService.Verify(m =>
m.PerformPost<StandardErrorResult, PostAlertModel>(
It.IsAny<string>(),
It.IsAny<PostAlertModel>(), out apiErrors
), Times.Once);
}
但我收到以下错误
Moq.MockException :
Expected invocation on the mock once, but was 0 times:
m => m.PerformPost<StandardErrorResult,PostAlertModel>(It.IsAny<String>(), It.IsAny<PostAlertModel>(), .apiErrors)
No setups configured.
如何验证方法是否被调用。
我正在使用Moq和NUnit
更新1
根据Sunny的评论,我修改了测试以使用如下的回调
var consumerNumber = ...
var trip = ...
var result = ...
StandardErrorResult apiErrors;
_mockRestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(
It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback<string, PostAlertModel, StandardErrorResult>
((s, m, e) => e.Errors = new System.Collections.Generic.List<StandardError>()
{
new StandardError { ErrorCode = "Code", ErrorMessage = "Message" }
});
_systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
Assert.That(apiErrors.Errors, Is.Not.Null);
这是执行测试时现在抛出的错误。
System.ArgumentException : Invalid callback. Setup on method with
parameters (String,PostAlertModel,StandardErrorResult&)
cannot invoke callback with parameters (String,PostAlertModel,StandardErrorResult).
at Moq.MethodCall.ThrowParameterMismatch(ParameterInfo[] expected, ParameterInfo[] actual)
at Moq.MethodCall.SetCallbackWithArguments(Delegate callback)
at Moq.MethodCallReturn`2.Callback(Action`3 callback)
Setup语句抛出此错误。
FYI。我正在使用Resharper 8并使用他们的测试运行器来执行我的测试。
如果我尝试将out参数添加到回调中,则代码将无法编译。
如果我将设置修改为
,我会收到同样的错误_mockRestCommunicationService.Setup(x => x.PerformPost<string, PostAlertModel>(
It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback
((string s, PostAlertModel m, StandardErrorResult e) => e.Errors = new System.Collections.Generic.List<StandardError>()
{
new StandardError { ErrorCode = "Code", ErrorMessage = "Message" }
});
答案 0 :(得分:3)
最好实际使用AAA而不验证模拟。设置您的方法以返回一些特定结果并断言已返回结果:
var myCommResult = new PostAlertModel();
_mockEestCommunicationService
.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors)
.Returns(myCommResult);
var response = _systemUnderTest.CreateTrip(consumerNumber, trip, out apiErrors);
Assert.AreSame(myCommResult, response);
以上将根据示例代码验证是否调用了该方法。
如果出于某种原因,问题中的代码并不真正代表真实代码,并且没有办法在返回方法时断言,而是可以使用Callback,并在错误中添加一些内容你可以验证。
类似的东西:
_mockEestCommunicationService
.Setup(x => x.PerformPost<string, PostAlertModel>(It.IsAny<string>(), It.IsAny<PostAlertModel>(), out apiErrors))
.Callback( (string s, PostAlertModel m, StandardErrorResult e) => e.Add("Some error to test");
稍后验证apiErrors是否包含您在回调中插入的错误。
答案 1 :(得分:0)
在我正在处理的项目中,我们使用了 out It.Ref<T>.IsAny
,其中 T 是输出参数类型(Moq 版本 4.14)。这是因为 out
用作参数修饰符,因此值为 passed by reference instead of by value。
在您的情况下,verify 方法可能如下所示:
_mockRestCommunicationService.Verify(
_ => _.PerformPost<StandardErrorResult, PostAlertModel>(
It.IsAny<string>(),
It.IsAny<PostAlertModel>(),
out It.Ref<StandardErrorResult>.IsAny
),
Times.Once
);
为确保没有其他意外调用发生,您还可以添加:
_mockRestCommunicationService.VerifyNoOtherCalls()