正在验证在 Task.Run 内部调用了 Mock 方法
Verifying Mock method was called inside Task.Run
当方法本身在传递给 Task.Run
的委托中被调用时,如何验证该方法是否在 mock 上被调用?到 mock.Verify
调用时,任务仍未执行。
我在 mock.Verify
之前尝试过 await Task.Delay
但这似乎让测试运行程序挂起。
之所以使用Task.Run
是为了卸载逻辑,以防止攻击者在执行时能够区分系统中是否存在电子邮件地址。
using System.Threading.Tasks;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace AsyncTesting
{
class MyController : Controller
{
public IEmailService EmailService { get; set; }
public MyController(IEmailService emailService)
{
EmailService = emailService;
}
public ViewResult BeginPasswordReset(string emailAddress)
{
BeginPasswordResetAsync(emailAddress);
return View();
}
private Task BeginPasswordResetAsync(string emailAddress)
{
return Task.Run(delegate
{
EmailService.Send(emailAddress);
});
}
}
internal interface IEmailService
{
void Send(string emailAddress);
}
internal class MyControllerTests
{
[TestMethod]
public void BeginPasswordReset_SendsEmail()
{
var mockEmailService = new Mock<IEmailService>();
var controller = new MyController(mockEmailService.Object);
const string emailAddress = "email@domain.com";
controller.BeginPasswordReset(emailAddress);
mockEmailService.Verify(es=>es.Send(emailAddress));
}
}
}
在您的任务中,您可以设置一个 ManualResetEvent(我们的测试代码阻止使用类似的东西:
Assert.IsTrue(yourEvent.WaitForOne(TimeSpan.FromSecond(<max time you want to wait>), "the event failed to run");
像这样:
public void BeginPasswordReset_SendsEmail()
{
const string emailAddress = "email@domain.com";
ManualResetEvent sendCalled= new ManualResetEvent(false);
var mockEmailService = new Mock<IEmailService>();
mockEmailService.Setup(m => m.Send(emailAddress)).Callback(() =>
{
sendCalled.Set();
});
var controller = new MyController(mockEmailService.Object);
controller.BeginPasswordReset(emailAddress);
Assert.IsTrue(sendCalled.WaitOne(TimeSpan.FromSeconds(3)), "Send was never called");
mockEmailService.Verify(es => es.Send(emailAddress));
}
进行一些快速研究,似乎可以使用 MSTest。例如
[TestMethod]
public async Task BeginPasswordResetAsync();
{
await BeginPasswordResetAsync("emailAddress");
mockEmailService.Verify...
}
当方法本身在传递给 Task.Run
的委托中被调用时,如何验证该方法是否在 mock 上被调用?到 mock.Verify
调用时,任务仍未执行。
我在 mock.Verify
之前尝试过 await Task.Delay
但这似乎让测试运行程序挂起。
之所以使用Task.Run
是为了卸载逻辑,以防止攻击者在执行时能够区分系统中是否存在电子邮件地址。
using System.Threading.Tasks;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace AsyncTesting
{
class MyController : Controller
{
public IEmailService EmailService { get; set; }
public MyController(IEmailService emailService)
{
EmailService = emailService;
}
public ViewResult BeginPasswordReset(string emailAddress)
{
BeginPasswordResetAsync(emailAddress);
return View();
}
private Task BeginPasswordResetAsync(string emailAddress)
{
return Task.Run(delegate
{
EmailService.Send(emailAddress);
});
}
}
internal interface IEmailService
{
void Send(string emailAddress);
}
internal class MyControllerTests
{
[TestMethod]
public void BeginPasswordReset_SendsEmail()
{
var mockEmailService = new Mock<IEmailService>();
var controller = new MyController(mockEmailService.Object);
const string emailAddress = "email@domain.com";
controller.BeginPasswordReset(emailAddress);
mockEmailService.Verify(es=>es.Send(emailAddress));
}
}
}
在您的任务中,您可以设置一个 ManualResetEvent(我们的测试代码阻止使用类似的东西:
Assert.IsTrue(yourEvent.WaitForOne(TimeSpan.FromSecond(<max time you want to wait>), "the event failed to run");
像这样:
public void BeginPasswordReset_SendsEmail()
{
const string emailAddress = "email@domain.com";
ManualResetEvent sendCalled= new ManualResetEvent(false);
var mockEmailService = new Mock<IEmailService>();
mockEmailService.Setup(m => m.Send(emailAddress)).Callback(() =>
{
sendCalled.Set();
});
var controller = new MyController(mockEmailService.Object);
controller.BeginPasswordReset(emailAddress);
Assert.IsTrue(sendCalled.WaitOne(TimeSpan.FromSeconds(3)), "Send was never called");
mockEmailService.Verify(es => es.Send(emailAddress));
}
进行一些快速研究,似乎可以使用 MSTest。例如
[TestMethod]
public async Task BeginPasswordResetAsync();
{
await BeginPasswordResetAsync("emailAddress");
mockEmailService.Verify...
}