当我从代码中的其他地方调用它时,我的方法工作正常,我添加了单元测试来测试这个方法,当它从测试方法调用时,它会在第一行引发异常。
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);
}
这是测试方法
public void VerifyPostToAzureQueue()
{
try
{
AlertNotification alertNotification = new AlertNotification();
alertNotification.DataCenters = "TestCenter";
alertNotification.TimeStamp = DateTime.Now;
Utils.PostToAzureQueue(alertNotification);
Assert.IsTrue(true);
}
catch
{
Assert.Fail();
}
}
当我在方法的第一行硬编码连接字符串时,它传递了这一行但在第二行中失败了。 当我从其他地方调用它时,该方法工作得很好。 请注意,测试方法是在单独的测试项目中。
答案 0 :(得分:5)
根据您上面的评论,您会看到一个空引用异常,因为您的代码可能是这一行:
CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"))
无法找到连接字符串。如您所述,您的测试函数与生产代码位于一个单独的项目中,因此StorageConnectionString
可能不在可访问的配置文件中。
很好地说明了为什么在你要使用它的代码中构建连接对象是个坏主意。您当前的PostToAzureQueue
方法会执行多项操作:
activealertsqueue
。这违反了Single Responsibility Principle。此方法应该做一件事:将消息发送到队列。您应该重构此方法以仅执行该操作,然后为其提供执行该操作所需的工具。所以它看起来像:
public static void PostToAzureQueue(AlertNotification alertNotification, CloudQueueClient client)
{
var queue = client.GetQueueReference("activealertsqueue");
queue.AddMessage(new CloudQueueMessage(alertNotification.Serialize()));
}
您的客户端应该在外部创建并injected到您的代码中(实际上它应该被注入到父类而不是这个方法中,但这是一个不同的讨论)。然后,您可以处理任何异常(例如,QueueNotExists
或在activealertsqueue
不存在时将抛出的任何异常)并重试调用PostToAzureQueue
的逻辑。通过从此方法中提取这些功能,您将简化此方法并使其更易于测试。