Friday, April 07, 2017

Automated Testing Logic Apps with SpecFlow (I)

I start this series of post, talking about how to test our Logic Apps with SpecFlow for Visual Studio 2015. This week I have attended the event "Automated Testing with Logic Apps and Specflow" by Michael Stephenson and I will put in practice some of the ideas that Michael Stephenson talked in that event.



I will use my demo scenario that I used on Global Integration Bootcamp 2017:


In this scenario, when I put an XML message with some orders in a Service Bus Queue, the Logic App gets the message, validates the XML, transform the XML, adds a contact in Insightly and for each order in the input XML, it sends a JSON message to another Service Bus Queue.

I begin my series of post with a Black-Box test, putting a message in de input queue and waiting for the result in the output queue.

With SpecFlow is very easy to express what I want to test, this is SpecFlow feature for my test:

Feature: Blackbox test for my MyIntegrationLogicApp
Testing Logic Apps with SpecFlow

Scenario: Blackbox - Receive a new orders on the queue
Given The queue is empty
| Queue name |
| neworders  |
And The queue is empty
| Queue name |
| neworder_json  |
When Put a new orders message with orders on input queue
| Queue name     |
| neworders |                 |
Then the output queue have messages
| Queue name     | Number of messages |
| neworder_json | 2                  | 

Now we have to implement our class to link with these requirements. I called it BlackboxSteps.cs and this is the structure and namespaces:

using System;
using System.IO;
using System.Xml;
using Microsoft.ServiceBus.Messaging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechTalk.SpecFlow;

namespace LogicAppUnitTestProject.Features.Whitebox
{
    [Binding]
    [Scope(Feature = "Blackbox test for my MyIntegrationLogicApp", Scenario = "Blackbox - Receive a new orders on the queue")]
    public class BlackboxSteps
    {
    }
}
For the Given conditions, I only have to connect to the queue with the name that I pass on the SpecFlow parameters and check that there isn't any message:

        [Given("The queue is empty")]
        public void CheckQueueIsEmpty(Table parameters)
        {
            var connectionString = "YOUR CONNECTION STRING";

            // Check the parameters
            string queueName = "";

            bool existParameter = parameters.Rows[0].TryGetValue("Queue name", out queueName);

            Assert.IsTrue(existParameter);

            // Check if there are messages
            var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
            BrokeredMessage receivedMessage = client.Peek();

            Assert.IsNull(receivedMessage);
        }
For the When condition, I only have to send an XML to the queue with the name that I pass on the SpecFlow parameters:

        [When("Put a new orders message with orders on input queue")]
        public void PutMessageOnQueue(Table parameters)
        {
            var connectionString = "YOUR CONNECTION STRING";

            // Check the parameters
            string queueName = "";

            bool existParameter = parameters.Rows[0].TryGetValue("Queue name", out queueName);

            Assert.IsTrue(existParameter);

            // Send the XML message
            var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
            XmlDocument ordersRequestXml = new XmlDocument();
            ordersRequestXml.LoadXml("C0001JoseMartin95625353GIB Customer10001200052016-11-20T14:26:00");
            MemoryStream mStream = new MemoryStream();
            ordersRequestXml.Save(mStream);
            mStream.Position = 0;
            var message = new BrokeredMessage(mStream);
            client.Send(message);
        }        
For the Then condition, I only have to receive the spected number of messages in the queue with the name. The number of messages and the queue name are SpecFlow parameters, If I receive more messages or less, my test will fail:
        [Then("the output queue have messages")]
        public void CheckOutputQueueMessages(Table parameters)
        {
            var connectionString = "YOUR CONNECTION STRING";

            // Check the parameters
            string queueName = "";
            string strNoMessages = "";
            int noMessages = 0;

            bool existParameterQueueName = parameters.Rows[0].TryGetValue("Queue name", out queueName);
            bool existParameterNoMessages = parameters.Rows[0].TryGetValue("Number of messages", out strNoMessages);

            Assert.IsTrue(existParameterQueueName);
            Assert.IsTrue(existParameterNoMessages);
            Assert.IsTrue(int.TryParse(strNoMessages, out noMessages));

            // Receive the messages
            var client = QueueClient.CreateFromConnectionString(connectionString, queueName, ReceiveMode.ReceiveAndDelete);
            for (int i = 0; i < noMessages; i++)
            {
                BrokeredMessage receivedMessage = client.Receive(new TimeSpan(0, 0, 30));
                Assert.IsNotNull(receivedMessage);
            }

            // Check if queue is null
            BrokeredMessage otherMessages = client.Peek();
            Assert.IsNull(otherMessages);
        }
The last step and the easiest is check that my test works. We run this test as wichever unit test we had:



In the Azure Portal, we can check how our Test and our Logic Apps worked:


This is a simple test, in next posts I will complicate it.

No comments: