I am currenlty at a client working on an integration project which will consist of a large number of integration points, schemas, and transforms. We really needed a way to test out each of our maps in a canned unit test for repeatable and consistent verification. I started with the model described by Gilles at:
http://blogs.msdn.com/gzunino/archive/2004/09/21/232629.aspx
http://blogs.msdn.com/gzunino/archive/2004/09/21/232429.aspx
However, one thing I wanted to change was the mapping from String-Stream-Transform and back and simply use the XslTransform and XsltArgumentList directly as exposed (though not documented) by Microsoft.XLANGs.BaseTypes.TransformBase through the Transform and TransformArgs properties.
Our environment of choice was Team System Unit Test. I stared by building up a utility method within our unit test framework to generically extract the XslTransform and XsltArgumentList from the appropriate BizTalk map within the Transform Assembly. I accomplished this by passing in the name of the map I wished to exercise and reflecting in to the assemby to retrieve teh XslTransform and XsltArgumentList. See the following.
public XmlDocument TransformWithBizTalkMap(FileStream sampleXML, string transformToTest)
{
string transformPath = @"..\..\..\Project.BizTalk.Transforms\bin\debug\Project.BizTalk.Transforms.dll";
XmlDocument xmlOut = new XmlDocument();
XslTransform xslTransform = new XslTransform();;
XsltArgumentList xsltArgumentList = new XsltArgumentList();
Assembly mapAssembly = Assembly.LoadFrom(transformPath);
foreach (Type mapType in mapAssembly.GetTypes())
{
if (mapType.Name == transformToTest)
{
//These methoods calls will get the Transform directly as XslTransform, not as a stream
PropertyInfo propXslTransform = mapType.GetProperty("Transform");
MethodInfo miXslTransform = propXslTransform.GetGetMethod();
if (miXslTransform != null)
{
Object obj = Activator.CreateInstance(mapType);
//get the actual transform
xslTransform = (XslTransform)miXslTransform.Invoke(obj, null);
}
//These methods will get the XslArgumentList directly as XsltArgumentList, not as a stream
PropertyInfo propXsltArgumentList = mapType.GetProperty("TransformArgs");
MethodInfo miXsltArgumentList = propXsltArgumentList.GetGetMethod();
if (miXsltArgumentList != null)
{
Object obj = Activator.CreateInstance(mapType);
//get the actual XsltArgumentList
xsltArgumentList = (XsltArgumentList)miXsltArgumentList.Invoke(obj, null);
}
BizTalkMap bizTalkMap = new BizTalkMap(xslTransform, xsltArgumentList);
Stream streamOut = bizTalkMap.TransformInstance(sampleXML);
xmlOut.Load(streamOut);
}
}
return xmlOut;
}
After I had the XslTransform and the XsltArgumentList for the BizTalk map I wanted to test I could now perform the test. I simply modified the BizTalkMap class presented by Gilles to accept the XslTransform and XsltArgumentList directly instead of building them up from the streams. Below is a copy of the updated class.
using System;
using System.Reflection;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.IO;
using System.Text;
namespace Project.Biztalk.UnitTest
{
public class BizTalkMap
{
private XslTransform xslTransform;
private XsltArgumentList xsltArgumentList;
public BizTalkMap(XslTransform transform, XsltArgumentList args)
{
xslTransform = transform;
xsltArgumentList = args;
}
public Stream TransformInstance(Stream inXml)
{
XslTransform transform = Transform;
XmlDocument xmlInDoc = new XmlDocument();
// Output stream
MemoryStream outStream = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(outStream, System.Text.Encoding.UTF8);
xmlInDoc.Load(inXml);
// Formatting options
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 2;
// Perform transformation - We do not specify a resolver
transform.Transform(xmlInDoc, TransformArgs, xmlWriter, null);
// Prepare the output stream
outStream.Seek(0, SeekOrigin.Begin);
return outStream;
}
private void StreamReader()
{
throw new Exception("The method or operation is not implemented.");
}
private XslTransform Transform
{
get {return xslTransform;}
}
private XsltArgumentList TransformArgs
{
get {return xsltArgumentList;}
}
}
}
Now with the Utility methods we are ready to tie into our Team Test framework and exercise each of our BizTalk maps. All we need to do is build out the TestMethods for each of the BizTalk Maps passing in simply a input xml FileStream and the name of the map to exercise. Hope this help you. Enjoy.........