C#:从测试方法调用时方法失败,否则工作正常

Neh*_*zem 2 c# unit-testing azure azure-sql-database

当我从代码中的其他地方调用它时,我的方法工作正常,我添加了单元测试来测试这个方法,当它从测试方法调用时,它会在第一行引发异常.

    public static void PostToAzureQueue(AlertNotification alertNotification)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
        CloudQueue queue = queueClient.GetQueueReference("activealertsqueue");
        queue.CreateIfNotExists();
        CloudQueueMessage message = new CloudQueueMessage(alertNotification.Serialize());
        queue.AddMessage(message);
    }
Run Code Online (Sandbox Code Playgroud)

这是测试方法

    public void VerifyPostToAzureQueue()
    {
        try
        {
            AlertNotification alertNotification = new AlertNotification();
            alertNotification.DataCenters = "TestCenter";
            alertNotification.TimeStamp = DateTime.Now;
            Utils.PostToAzureQueue(alertNotification);

            Assert.IsTrue(true);
        }
        catch
        {
            Assert.Fail();
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我在方法的第一行硬编码连接字符串时,它传递了这一行但在第二行中失败了.当我从其他地方调用它时,该方法工作得很好.请注意,测试方法是在单独的测试项目中.

Nec*_*ras 5

根据您上面的评论,您看到一个空引用异常,因为您的代码,可能是这一行:

CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"))
Run Code Online (Sandbox Code Playgroud)

无法找到连接字符串.如您所述,您的测试功能与生产代码位于一个单独的项目中,因此StorageConnectionString可能不在可访问的配置文件中.

这很好地说明了为什么在你要使用它的代码中构建连接对象是个坏主意.您当前的PostToAzureQueue方法做了多件事:

  1. 它会为您的帐户获取连接设置.
  2. 它会为您的帐户创建一个客户端.
  3. activealertsqueue如果它不存在,它会创建一个.
  4. 它向该队列发送消息.

这违反了单一责任原则.此方法应该做一件事:将消息发送到队列.您应该重构此方法以仅执行该操作,然后为其提供执行该操作所需的工具.所以它看起来像:

public static void PostToAzureQueue(AlertNotification alertNotification, CloudQueueClient client)
{
    var queue = client.GetQueueReference("activealertsqueue");
    queue.AddMessage(new CloudQueueMessage(alertNotification.Serialize()));
}
Run Code Online (Sandbox Code Playgroud)

您的客户端应该在外部创建并注入到您的代码中(实际上它应该注入到父类而不是这个方法中,但这是一个不同的讨论).然后,您可以处理任何异常(例如,a QueueNotExists或者如果activealertsqueue不存在则抛出的任何异常)并重试逻辑PostToAzureQueue调用的位置.通过从此方法中提取这些功能,您将简化此方法并使其更易于测试.