【问题标题】:Why is azure storage queue access so slow when unit testing?为什么单元测试时Azure存储队列访问这么慢?
【发布时间】:2013-05-25 07:19:39
【问题描述】:

我在尝试使用实时 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);
    }
}

当然,我们非常感谢您的洞察力。

【问题讨论】:

    标签: unit-testing azure-storage vs-unit-testing-framework azure-storage-queues


    【解决方案1】:

    我怀疑这与 Azure 队列无关,而是与 .NET 试图确定您的代理设置有关。如果您进行其他一些随机 System.Net 调用而不是调用队列存储会发生什么?

    在你的应用程序的开头试试这行代码:

       System.Net.WebRequest.DefaultWebProxy = null;
    

    【讨论】:

    • 谢谢。似乎工作得很好。我不能说我完全理解这是什么,以及插入此代码是否有不利之处,但我会寻找它。如果您对此有更多话要说,将不胜感激。大有帮助!
    • AND... 因为我的最终目标是一个 DLL(供内部使用,而不是供公众使用),所以我不想对用户的代理设置做出假设。添加@kwill 建议的代码效果很好。我尝试了另一个建议,在 .config 文件中为“默认代理”设置“useDefaultCredentials”,但这没有任何作用。所以也许我需要将我自己的部分添加到 .config 文件中并将其留给用户?味道不好闻……
    • 如果您正在构建 DLL,那么您不想更改代理设置。您可以将其留给用户(或应用程序开发人员)来管理应用程序的代理设置。出于测试目的保留此代码很好,但您应该在创建其他人将使用的构建之前将其删除。
    猜你喜欢
    • 1970-01-01
    • 2012-02-13
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2012-11-05
    • 2013-09-19
    • 2013-09-06
    相关资源
    最近更新 更多