如何使用 MSpec 为 ASP.NET MVC 3 AsyncController 编写测试
我想为 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
的结果?
I want to write a TaskController
for an ASP.NET MVC 3 application to some long running tasks, like sending a newsletter to the users of the site. I thought using an AsyncController
would be appropriate as sending emails might take a while, and I want to be able to save some state to the database when the task finishes running.
Being the properly brought up developer that I am (:þ), and being really into BDD, I naturally want to start off with a spec using MSpec.
Imagine my controller looks like this:
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
}
}
How does one go about writing specs for AsyncControllers? Imagine I start with the following specification:
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;
}
Should I be calling the SendMailAsync
method for the test? I actually feels yucky.
How do I deal with the result from SendMailCompleted
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我终于找到了至少一种方法。我确信还有其他可能更好的方法,但这里是:
声明一个将用作等待句柄的 AutoResetEvent 和一个将被设置为触发的 EventHandler当异步操作完成时。然后在
Because
块(对应于单元测试的Act
部分)中对AutoResetEvent
调用WaitOne
:如果您使用 NUnit 或任何其他测试框架而不是 MSpec 编写单元测试,应该也可以工作。
Well, I finally figured out at least a way to do it. I'm sure there are other and probably better ways, but here goes:
Declare an
AutoResetEvent
that will be used as wait handle and anEventHandler
that will be set up to fire when the async action completes. Then in theBecause
block (corresponding to theAct
part of unit testing) callWaitOne
on theAutoResetEvent
:This should work as well if you're writting unit tests with NUnit or any other test framework instead of MSpec.