我在尝试将单元测试与实时 Azure 存储队列一起使用时遇到了一些困难,因此我一直在编写越来越简单的示例来尝试隔离问题。简而言之,这似乎是正在发生的事情:
队列访问显然(并且适当地)延迟加载。不过,在我的 MVC 应用程序中,当我真的需要访问队列时(在我的情况下,当我调用 CloudQueue.Exists 方法时)它非常快。不到十分之一秒。但是,非常相同的代码在单元测试的上下文中运行时大约需要 25 秒。
我不明白为什么会有这种差异,所以我制作了一个简单的控制台应用程序,它可以写入一些内容,然后从 Azure 队列中读取它。控制台应用程序在第一次运行时也需要 25 秒——在随后的运行中大约需要 2.5 秒。
现在是真正奇怪的行为。我创建了一个包含三个项目的 Visual Studio 2012 解决方案——一个 MVC 应用程序、一个控制台应用程序和一个单元测试项目。这三个都调用相同的静态方法,该方法检查队列是否存在,如果不存在则创建它,向其中写入一些数据并从中读取一些数据。我在该方法中对 CloudQueue.Exists 的调用设置了一个计时器。这是交易。当从 MVC 应用程序调用该方法时,无论队列是否确实存在,CloudQueue.Exists 方法都会在大约十分之一秒内始终完成。从控制台应用程序调用该方法时,第一次调用需要 25 秒,后续调用大约需要 2.5 秒。当从单元测试中调用该方法时,它始终需要 25 秒。
更多信息:碰巧当我创建这个虚拟解决方案时,我碰巧将我的静态方法(QueueTest)放在控制台应用程序中。奇怪的是——如果我将 Visual Studio 中的默认启动项目设置为控制台应用程序,那么单元测试突然需要 2.5 秒。但是如果我将 Visual Studio 中的启动项目设置为 MVC 应用程序(或单元测试项目),那么单元测试需要 25 秒!
所以....有没有人知道这里发生了什么?我很困惑。
代码如下:
控制台应用程序:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(QueueTest("my-console-queue", "Console Test"));
}
public static string QueueTest(string queueName, string message)
{
string connectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
CloudQueue queue = queueClient.GetQueueReference(queueName);
DateTime beforeTime = DateTime.Now;
bool doesExist = queue.Exists();
DateTime afterTime = DateTime.Now;
TimeSpan ts = afterTime - beforeTime;
if (!doesExist)
{
queue.Create();
}
CloudQueueMessage qAddMessage = new CloudQueueMessage(message);
queue.AddMessage(qAddMessage);
CloudQueueMessage qGetmessage = queue.GetMessage();
string response = String.Format("{0} ({1} seconds)", qGetmessage.AsString, ts.TotalSeconds);
return response;
}
}
MVC 应用程序(家庭控制器):
public class HomeController : Controller
{
public ActionResult Index()
{
return Content(Program.QueueTest("my-mvc-queue", "Mvc Test"));
}
}
单元测试方法:(注意,目前预计会失败!)
[TestClass]
public class QueueUnitTests
{
[TestMethod]
public void CanWriteToAndReadFromQueue()
{
//Arrange
string qName = "my-unit-queue";
string message = "test message";
//Act
string result = Program.QueueTest(qName, message);
//Assert
Assert.IsTrue(String.CompareOrdinal(result,message)==0);
}
}
当然,非常感谢洞察力。