Nehad Hazem
Nehad Hazem

Reputation: 69

C#: Method fails when called from test method but works fine otherwise

I have method works fine when I call it from other places in the code, I added unit test to test this method and when it's being called from the test method it throws exception in the very first line.

    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);
    }

And here is the test method

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

            Assert.IsTrue(true);
        }
        catch
        {
            Assert.Fail();
        }
    }

When I hard code the connection string in the first line in the method, it passed this line but failed in the 2nd line. The method works just fine when I call it from anywhere else. Please note that the test method is in separate test project.

Upvotes: 2

Views: 189

Answers (1)

Necoras
Necoras

Reputation: 7542

Based on your comments above, you are seeing a null reference exception because your code, probably this line:

CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"))

isn't able to find a connection string. As you noted, your test function is in a separate project from your production code, so the StorageConnectionString probably isn't in an accessible configuration file.

Which nicely demonstrates why it's a bad idea to build connection objects in your code where you're going to use it. Your current PostToAzureQueue method does multiple things:

  1. It gets connection settings for your account.
  2. It creates a client for your account.
  3. It creates an activealertsqueue if it doesn't exist.
  4. It sends a message to that queue.

This violates the Single Responsibility Principle. This method should do one thing: send a message to a queue. You should refactor this method to do only that one thing, and then provide it with the tools that it needs to do that thing. So it would look something like:

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

Your client should be created externally and injected into your code (really it should be injected into the parent class and not this method, but that's a different discussion). You can then handle any exceptions (say, a QueueNotExists or whatever would be thrown if activealertsqueue doesn't exist) and retry logic where PostToAzureQueue is called. By extracting these pieces of functionality from this method you will simplify this method and make it more testable.

Upvotes: 5

Related Questions