【问题标题】:How to write tests for ASP.NET MVC 3 AsyncControllers with MSpec如何使用 M Spec 为 ASP.NET MVC 3 异步控制器编写测试
【发布时间】:2011-03-12 00:22:56
【问题描述】:

我想为 ASP.NET MVC 3 应用程序编写一个TaskController 以完成一些长时间运行的任务,例如向网站用户发送新闻通讯。我认为使用AsyncController 是合适的,因为发送电子邮件可能需要一段时间,并且我希望能够在任务完成运行时将一些状态保存到数据库中。

作为我 (:þ) 的一名受过良好教育的开发人员,并且非常热衷于 BDD,我自然想从使用 MSpec 的规范开始。

想象一下我的控制器是这样的:

public class TaskController : AsyncController
{    
    readonly ISession _session;

    public TaskController(ISession session)
    {
        _session = session;
    }

    public void SendMailAsync()
    {
        // Get emails from db and send them
    }

    public ActionResult SendMailCompleted()
    {
        // Do some stuff here
    }
}

如何为 AsyncController 编写规范?想象一下,我从以下规范开始:

public class TaskControllerContext
{
    protected static Mock<ISession> session;
    protected static TaskController controller;
    protected static ActionResult result;
}

[Subject(typeof(TaskController), "sending email")]
public class When_there_is_mail_to_be_sent : TaskControllerContext
{
    Establish context = () =>
    {
        session = new Mock<ISession>();
        controller = new TaskController(session.Object);
    };

    // is this the method to call?
    Because of = () => controller.SendMailAsync();

    // I know, I know, needs renaming...
    It should_send_mail;
}

我应该调用SendMailAsync 方法进行测试吗?我真的觉得很恶心。 我如何处理来自SendMailCompleted 的结果?

【问题讨论】:

    标签: testing asp.net-mvc-3 bdd mspec asynccontroller


    【解决方案1】:

    好吧,我终于找到了至少一种方法。我敢肯定还有其他可能更好的方法,但这里是:

    声明将用作等待句柄的 AutoResetEvent 和将设置为在异步操作完成时触发的 EventHandler。然后在Because 块中(对应于单元测试的Act 部分)在AutoResetEvent 上调用WaitOne

    static AutoResetEvent waitHandle; 
    static EventHandler eventHandler;
    static int msTimeout = 5000;
    static IEnumerable<Email> response;
    
    Establish context = () =>
    {
        toSend = new List<Email>
        {
            // Emails here
        };
    
        // Prepare the mock objects
        session.Setup(x => x.All<Email>()).Returns(toSend.AsQueryable());
        mailer.Setup(x => x.SendMail(Moq.It.IsAny<IEnumerable<Email>>()))
            .Returns(toSend);
    
        // Set up the wait handle    
        waitHandle = new AutoResetEvent(false);
        eventHandler = (sender, e) => waitHandle.Set();
        controller.AsyncManager.Finished += eventHandler;
    };
    
    Because of = () =>
    {
        controller.SendMailAsync();
        if (!waitHandle.WaitOne(msTimeout, false)) {}
    
        response = (IEnumerable<Email>) controller.AsyncManager
            .Parameters["sentMails"];
    };
    
    It should_send_mail = () => response.Any().ShouldBeTrue();
    

    如果您使用 NUnit 或任何其他测试框架而不是 MSpec 编写单元测试,这应该也可以。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 1970-01-01
      • 2021-01-24
      相关资源
      最近更新 更多