Unit Testing a BizTalk Solution: Part I







“Fewer defects, less debugging, more confidence,better design, and higher productivity in my programming practice”
(Kent Beck)



This post tackles different methods that can be used to successfully unit test a BizTalk Solution. The mentioned approaches utilize a set of different tools to facilitate and organize how unit tests are created, maintained and executed.

Although BizTalk Software Factory is not a pre-requisite to fully understand the presented content, a brief overview is suggested as we will be ultimately using its solution structure and support classes to create our unit tests.

Testing XML Schemas

In order to successfully test XML Schemas we need to first comprehend the real purpose of a XML Schema, (Sperberg-McQueen & Thompson, 2000) define XML Schemas as:

“XML Schemas express shared vocabularies and allow machines to carry out rules made by people. They provide a means for defining the structure, content and semantics of XML documents.”

Based on this definition, when testing XML schemas the focus should be on the validation of the targeted structure, content and semantic. It is worth it to spend time elaborating acceptable and unacceptable sample xml messages in order to verify if the constraints implied by the target XML schema are being correctly applied.

The set of unit tests should validate the compliance of each XML document instance with the XML Schema being tested. Unit tests being executed against acceptable XML Instances should pass the XML Schema validation, whereas Unit Tests for unacceptable XML Instances should expect validation errors as a condition for a successful test.

The steps needed to test a XML Schema are as straightforward as creating a simple Unit Test logic to load a XML Instance document and validate it against the XML Schema being tested.

Testing XML Schemas with NUnit

The Biztalk Software Factory facilitates the work needed to create the infrastructure required to unit test a Biztalk Solution. A Biztalk Software Factory based solution should have a [ProjectName].UnitTests project including helper classes to support tests created on this project.

As the name suggests, the XmlSchemaValidator class (located in the XmlSchemaValidator.cs file), can be used to validate xml document instances against XML Schemas. The code below exemplifies the usage of XmlSchemaValidator:

[Test]
public void ValidMessageSchemaValidationTest()
{

bool valid = XmlSchemaValidator.ValidateAgainstSchema(@”..\..\TestData\myValidXmlInstance.xml”, @”..\..\Schemas\mySchema.xsd”);

if (!valid)
{

throw new XmlSchemaValidationException(“The xml document instance myValidXmlInstance.xml is not compliant with the XML schema mySchema.xsd. Check the output trace for more details.”);

}

}

[Test]
public void InvalidMessageSchemaValidationTest()
{

bool valid = XmlSchemaValidator.ValidateAgainstSchema(@”..\..\TestData\myInvalidXmlInstance.xml”, @”..\..\Schemas\mySchema.xsd”);

if (valid)
{

throw new ApplicationException(“The non compliant xml document instance myInvalidXmlInstance.xml passed on the XML schema validation against the mySchema.xsd schema.”);

}

}

Testing BizTalk Maps

BizTalk Maps are used to transform documents from a source schema into a new document of a target schema. We can use two approaches to verify if the transformation is being performed correctly:



1.Validate the map output document against the target schema.


2.Validate the map output document against the desired output xml instance.

Testing BizTalk Maps with NUnit

The code below exemplifies how to test BizTalk Maps against a desired output xml instance:

[Test]
public void MapTest()
{

MapValidator.ExecuteMapInMemory(new MyProject.Maps.MyMap(), inputPath, outputPath);
MapValidator.ValidateMapOutput(outputPath, expectedFilePath);

}

Testing BizTalk Maps against a target schema:

[Test]
public void MapTest()
{

MapValidator.ExecuteMapInMemory(new MyProject.Maps.MyMap(), inputPath, outputPath);
bool valid = XmlSchemaValidator.ValidateAgainstSchema(outputPath,@”..\..\Schemas\mySchema.xsd”);

if (!valid)
{

throw new XmlSchemaValidationException(“The output document generated by MyMap is not compliant with the XML schema mySchema.xsd. Check the output trace for more details.”);

}

}

Testing BizTalk Pipelines

Testing Pipelines is not different from testing any other component, the tricky part is the mechanism used to mimic the BizTalk Runtime Engine so the pipeline can be instantiated and executed. That’s exactly where Winterdom Pipeline Testing Framework enters in scene; see (Restrepo, 2007) for more details.

Winterdom Pipeline Testing Framework will provide support to execute pipelines as well as validate output messages in order to verify if any desired processing was made accordingly. If needed, pipeline components can also be tested independently, which allows us creating even richer pipeline unit tests.

As an example, it is possible to have an unit test dedicated to each of the pipeline components of a given pipeline and finally a unit test for the whole pipeline.

Adding message context properties, altering message content, and changing state of external systems are just a few examples of actions that might be taken in a Pipeline. Therefore, depending on the pipeline in question, applying effective testing might be a simple or complex task.

The unit test should validate if all the intended processing and modifications were made correctly, and as stated before, sometimes changes are not only restricted to the output message.

Testing BizTalk Pipeline Components with NUnit

The code below exemplifies how to test an entire pipeline using the Winterdom Pipeline Testing Framework:

[Test]
public void CustomHeaderCheck()
{

SendPipelineWrapper pipeline = GetSendPipeline();

//Whatever message, this test is focused on the message context
//although there is a content validation at the end to make sure that the
//message came out properly
IBaseMessage inputMessage = TestData.GetTestMessage(inputMessagePath);

//Executes the pipeline and gets the resultant message
IBaseMessage outputMessage = pipeline.Execute(vipDatabaseResyncStartMessage);

string headerXmlFragment = outputMessage.Context.Read(“OutboundCustomHeaders”, “http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties”).ToString();

Dictionary contentValidationInfoList = new Dictionary();
contentValidationInfoList.Add(“//Header/Action”, “SubmitOrder”);

//Validates the output message header
Helper.XmlSchemaValidator.ValidateXmlDocumentContent(headerXmlFragment, contentValidationInfoList);

}

private SendPipelineWrapper GetSendPipeline()
{

SendPipelineWrapper wrapper = Winterdom.BizTalk.PipelineTesting.PipelineFactory.CreateEmptySendPipeline();

wrapper.AddComponent(new PipelineComponent1(), PipelineStage.PreAssemble);

wrapper.AddComponent(new PipelineComponent2(), PipelineStage.PreAssemble);

wrapper.AddComponent(new PipelineComponent3(), PipelineStage.Encode);

return wrapper;
}

Wrapping Up

After having some practice with BizTalk unit tests, you will notice that many of them will actually validate the proper execution of components and artifacts altogether. Although assuring that each piece works as designed separately will not guarantee any success when testing in a composed scenario, enormous amount of time will be saved when troubleshooting.

Another important point to be mentioned is that with Unit Tests the overall implementation quality tends to be increased as testing is being introduced on the early stages of your development process.

On Part II, some techniques will be shown explaining how to unit test BizTalk Business Rules and Orchestrations.