我正在尝试在要测试的方法中模拟服务调用。
方法体如下所示:
public string OnActionException(HttpActionContext httpRequest, Exception ex)
{
var formattedActionException = ActionLevelExceptionManager.GetActionExceptionMessage(httpRequest);
var mainErrorMessage = $"[{formattedActionException.ErrorId}]{formattedActionException.ErrorMessage}, {ex.Message}";
this.LogError(mainErrorMessage, ex);
if (this._configuration.MailSupportOnException)
Task.Run(async () => await this._mailService.SendEmailForThrownException(this._configuration.SupportEmail, $"{mainErrorMessage} ---> Stack trace: {ex.StackTrace.ToString()}"));
return $"(ErrID:{formattedActionException.ErrorId}) {formattedActionException.ErrorMessage} {formattedActionException.KindMessage}";
}
我想在测试中模拟的是:
Task.Run(async () => await this._mailService.SendEmailForThrownException(this._configuration.SupportEmail, $"{mainErrorMessage} ---> 堆栈跟踪:{ex.StackTrace.ToString()}"));
测试方法如下:
[TestMethod]
public void We_Send_System_Exception_On_Email_If_Configured_In_Settings()
{
// arrange
this._configurationWrapperMock.Setup(cwm => cwm.MailSupportOnException)
.Returns(true);
this._mailServiceMock.Setup(msm => msm.SendEmailForThrownException(It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(0));
// act
var logger = new ApiLogger(this._configurationWrapperMock.Object, this._mailServiceMock.Object);
logger.OnActionException(
new HttpActionContext(
new HttpControllerContext()
{
Request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new System.Uri("https://www.google.bg/")
}
},
new ReflectedHttpActionDescriptor() { }
),
new System.Exception());
// assert
this._mailServiceMock.Verify(
msm => msm.SendEmailForThrownException(It.IsAny<string>(), It.IsAny<string>()),
Times.Once);
}
问题是该方法从未被调用,所以我的断言失败了。
编辑:我可以将我的问题改为:我需要如何重写我的方法以使其可测试?
最佳答案
你的代码是经典情况下的应用Humble Object Pattern .
在这种情况下,您所要做的就是将 Task.Run
提取到一个虚拟方法中,然后部分模拟 SUT 并覆盖该虚拟方法:
public class ApiLogger
{
...
public string OnActionException(Exception ex)
{
...
if (this._configuration.MailSupportOnException)
RunInTask(...);
...
}
public virtual Task RunInTask(Action action)
{
return Task.Run(action);
}
}
然后测试看起来像:
[TestMethod]
public void We_Send_System_Exception_On_Email_If_Configured_In_Settings()
{
...
var logger = new Mock<ApiLogger>(MockBehavior.Default,
new object[]
{
this._configurationWrapperMock.Object,
this._mailServiceMock.Object
}).Object;
logger.OnActionException(...);
this._mailServiceMock.Verify(
msm => msm.SendEmailForThrownException(It.IsAny<string>(), It.IsAny<string>()),
Times.Once);
}
关于c# - 使用在 Task.Run 内部调用的 Moq 方法进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47561264/