当我从代码中的其他地方调用它时,我的方法工作正常,我添加了单元测试来测试这个方法,当从测试方法调用它时,它会在第一行抛出异常。
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();
}
}
当我在方法的第一行中硬编码连接字符串时,它通过了这一行,但在第二行中失败了。 当我从其他地方调用该方法时,该方法工作得很好。 请注意,测试方法位于单独的测试项目中。
请您参考如下方法:
根据您上面的评论,您会看到空引用异常,因为您的代码可能是这一行:
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到你的代码中(实际上它应该被注入(inject)到父类而不是这个方法中,但这是一个不同的讨论)。然后,您可以处理任何异常(例如,QueueNotExists
或如果 activealertsqueue
不存在则抛出的任何异常)并重试 PostToAzureQueue
所在的逻辑叫。通过从此方法中提取这些功能,您将简化该方法并使其更易于测试。