c# - 验证在 Task.Run 中调用了 Mock 方法

标签 c# unit-testing moq mstest

当方法本身在传递给 Task.Run 的委托(delegate)中被调用时,我如何验证该方法是否在 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));
}

关于c# - 验证在 Task.Run 中调用了 Mock 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31728596/

相关文章:

c# - 如何重构静态方法以便测试我的方法?

c# - Unity3d 中的 Material 、着色器和对象轮廓

c# - 是否可以加快测试 nservicebus 超时管理器的过程?

javascript - sinon.stub() vs sinon.sandbox.stub()?

c# - .NET 单元测试 - 带有 MVC 的 Moq/xUnit 框架,未返回预期结果

c# - 使用 Moq 和 TDD,从哪里开始?

c# - 在 Windows Phone 7 中打开本地 docx、pptx 和 pdf

C# - 如何在 C# 中使用整数来确定从 mysql 表中选择的限制

c# - 程序红外接收器

objective-c - 使用 XCode 4 进行单元测试的链接错误?