Tag Archive: Visual Studio


The out of the box unit test framework for BizTalk maps leaves a lot to be desired. Effectively a Visual Studio map unit test is the equivalent of choosing to validate your map, which involves running an instance of an input message through your map and validating the output of the map against it’s schema. If you want to check the values in the output message then it is up to you to implement your own logic for this, and if you want to test variations in some of the elements in your input message then you really need to be creating and managing more copies of the input message which can quickly escalate into a management nightmare. This doesn’t leave one with the utmost confidence in their map when making changes to it, nor does it assure one that all the functional requirements are being catered for.

The BizTalk Map Testing Framework provides a solution to many of these problems. It allows you to run a map against an instance of an input message and it will compare the actual output of the map against a pre-prepared expected output message. This is referred to as a base test.

It also allows you make multiple additional tests with variations of elements in the input message based on the same file, and validates the output against a variation of the output message also based on the same file. These variations are catered for through collections (one for the input message and one for the output message) of xpath statements which contain the elements which need to be varied for that given test case. The test implementor would then create test cases, each test case containing different values which will be replaced in the input and output message based on the xpath statements.

The BizTalk Map Testing Framework also comes with overridable methods called OnTestExecuting and OnTestExecuted which allow you to perform your own custom validation before or after the maps have been executed (note that OnTestExecuted might be run after the map has been executed but it will still be run before the test cases themselves have been executed). This is made easy as the framework also includes some handy helper classes that let you extract values from either the input or output messages to validate them, or even to replace the values in them with a pre-prepared value. This is especially handy when the output message will contain some dynamic values such as a GUID or the current date time and you want to perform some custom validation on them before replacing them with a static value so that the static comparison against the output message still succeeds.

Let’s illustrate this with an example. Our input message contains an element called EventType and if it has a value of U then a value of Update will be mapped to an element called EventType in the output message, if the value in the input is D the value in the output is Delete, and if the element has a blank value or doesn’t exist in the input then a value of Unknown should be mapped to the output, if the input has any other value then the output element shouldn’t exist at all. We also have a repeating element in the input message called EventCode which can exist upto 4 times, and an EventCodes element in the output message which is a concatenation of all the source elements but will be suppressed if there are no EventCode elements in the source message. We also want an element called Id in the output message to contain a valid randomly generated GUID.

The map and the example instances which we are going to use in our test class are as below.

Before we start we want to ensure that the projects containing our BizTalk maps and schemas are set to allow for unit testing.  Do this by opening the project properties, browsing to the deployment tab and enabling unit testing.  Ensure you deploy the solution after doing this.

We now need to create a test project, add a reference to our projects containing the BizTalk maps and schemas (only necessary if we want to do schema validation), add a reference to the MapTestFramework.Common dll, and references to the Microsoft.BizTalk.TestTools and Microsoft.XLANGS.BaseTypes dlls.

Next up we add a test class (remember to decorate your class with the TestClass attribute) and inherit from the MappingFixture base class contained within the MapTestFramework.Common namespace. You’ll now want to override the CreateMap method and the SourcePathBase and ExpectedPathBase properties as below so that the test class knows which map, input file, and output file it is going to be using.

Now we want to implement our base test which will perform a static comparison of our output file to the actual file that was generated. The base test should look like below.

When you attempt to execute the base test you will notice that it fails since the value of the GUID is randomly generated and thus doesn’t match the GUID in our expected output file. In order to cater for this we would need to override the OnTestExecuted method as below such that it validates the GUID in the actual output file (we’ll throw in schema validation here too just for fun, note that the below implementation of schema validation has many limitations but I have shown this for the sake of brevity), and then replace the GUID with the one that has been set in the static expected output file.  Note the usage of methods within the XmlHelper namespace which are used to read in elements from the output file and to replace them as well.

The base test should now execute and return a succesful result.

Now we need to implement a test which checks for the different values in the EventType element.  Create a new test method and instantiate an object of type MapTestCases passing two arrays of strings into the constructor, the first array containing a list of xpath statements that we want to use to manipulate the source message before the test is executed, and the second array containing a list of xpath statements that are used to manipulate the expected output file before comparing it to the actual output file.  You can obtain these xpath statements from the Visual Studio schema editor or through a tool such as DanSharp XMLViewer.  The MapTestCases object instantiation should look like the below (notice that I have removed all the namespaces in the xpath statements to make the validation namespace agnostic, it is your choice whether you want to do this or not).

You will now want to add test cases, which are different scenarios based on the xpath statements for the input file and the expected output file, as below.

In the above screenshot the first TestCase prescribes that if the EventType in the input message is U then the EventType in the output message must be Update.  The third TestCase prescribes that if there is no EventType element in the input message then the EventType in the output message must have a value of Unknown.  The fifth TestCase prescribes that if the value of EventType in the input message is OtherValue then there should be no EventType element in the output message.

Lastly you will want to instruct the test method that it should now execute the map test against all the test cases that you have added to the collection as below.  Each one of the TestCases will be executed when the test method is executed and only if all pass will the test method be considered succesful.

The test for the EventCodes is somewhat different because there are repeating elements in the input message.  The trick here is that if you want your xpath collection to include multiple iterations of the same node and you are expecting to set some of the nodes to null, then you must specify the nodes in backwards order.  This is just logical because if you have 4 nodes and you set the first node to null then when you try to access the 4th node it will not exist because it is now actually the 3rd node.  Thus you must start by setting the last node to have a null value and then work your way backwards.  I have implemented this test method as below.

Some other things to consider.

  • I have not as yet been able to get the map test framework to work with a map in which the input message is an envelope schema containing an xsd:any node which links to an external xslt file.  I have reverted to using Visual Studio map tests for this map.
  • Executing the map tests will result in lots of files being created in the expected output file folder.  You will probably want to add a TestCleanUp method to your test class which deletes all the unnecessary files.
  • You will want to think of a smart folder pattern to store all your map files.  This will make it a lot easier to manage all the input and output files.
  • You’ll want to ensure that your BizTalk projects have unit testing disabled in your release build which you use to create deployments for your QA/Production environments.  The problem is that whenever you deploy based on your release profile and go back to your debug profile you will get a build error when you try to build your solution since the unit testable BizTalk artifacts aren’t deployed.  I work around this by creating an extra build profile which has unit testing enabled on my BizTalk projects but doesn’t build my unit testing projects, and everytime I have deployed a release build and want to go back to debug I will first do a deploy on the intermediate build profile and then go back to the debug profile.
  • It is possible to have your map test case contain an xpath statement for a record/complex type element in your input or output message which contain multiple elements within it, and instead of just passing a string value into the individual test cases you can pass in the XML for all the contained elements (don’t include the XML tags for the record/complex type element itself).

I have uploaded a zipped version of my solution containing my BizTalk Server 2010 project and my map test project.  Feel free to download and experiment with it.

Advertisements

This week I ran into the most bizarrely annoying problem, and I found that there was very little information available to guide me.

I had a solution that included a BizTalk WCF-NetMsmq receive location for which I had published metadata as well. However, every time I tried to generate proxy code, either using Visual Studio’s add service reference or the Svcutil command line tool, I ended up getting the below error.

Some posts on the blogosphere suggested all the schema’s element form default should be set to qualified. This didn’t sit right with me because I am sure that WCF happily supports different XML semantics.

Other suggestions (for example ) were to play with the options available in the add service reference and Svcutil tools, suggesting to generate message contracts, toggle reusing external references, and even override the serializer that was used. None of these options worked for me.

Another suggestion was to revert back to using .Net 2.0 style web references instead. Once again a suggestion that I did not want to consider

Others mentioned that the problem could be with my WSDL, but i had used the BizTalk WCF publishing wizard. Surely this could not have steered me wrong? I decided to investigate anyways. I attempted to isolate the problem by cutting down on the operations that the WCF service contained till I isolated the problem to a specific operation. I then dove into the schema (which for the record was not created by me :)) and found that there was an element with a Max Occurs set to 0. DOH!!! Fixing this setting allowed for proxy code to be happily generated from my WSDL.  Further investigation shows that if you set Max Occurs to 0 for a record or a any simple element type then you wont run into problems, however if the element has a restriction on it (such as an enumeration or a regular expression pattern) then this could potentially cause problems.

Takeaway is that if you encounter the same error as me, chances are that you have a problem with one of your schemas, as the BizTalk WCF publishing wizard is fairly trustworthy and does a reasonably good job at making sure that your metadata is in a usable state.

When creating schemas I typically follow the rule that each xsd file contains one root node only.

However when dealing with schemas that have been generated from metadata it is quite common for schemas to be generated with multipe root nodes.  In the case of web services all the request and response schema definitions across all the operations would be generated in one file, and similar behavior would be observed when generating schemas for the WCF-SQL adapter.  I would recommend sticking with this file structure, as it will minimize the pain you need to go through in case you need to regenerate the schemas and just want to overwrite the existing files.

How bad a typist does one have to be to misspell HelloWorld?

By default when you deploy a project that contains one of these multi root node schemas, all the schemas are available to the BizTalk runtime.

What you’ll quickly find though is that if you try to use options such as validate instance or generate instance, BizTalk will always do so with the first root node defined in the xsd file.   Luckily there is a way to override this by changing the “Root Reference” property against the schema.  You will see this property by clicking on the “Schema” node which is at the top of the schema hierarchy and then looking in the properties section of Visual Studio.

If you click on the dropdown, you will be faced with a list of all the root nodes in the schema file.  Choosing one of the root nodes will now instruct Visual Studio to treat that root node as the only valid one for that schema file.

The implication of this is that you can now run validate instance and generate instance against that schema file for the root node you have specified.  However another implication is that when you do a deployment from Visual Studio, you will find that only the root node that was set in root reference has been deployed, the rest of the root nodes are not available to the BizTalk runtime.

Where have all the schemas gone?

So moral of the story is that Root Reference is a powerful property that will allow you to validate or generate instances of the correct root node in your schema file, and can also be used to only deploy one of the root nodes defined in the schema file.  If you want to deploy all the root nodes in the schema file, do remember to set the Root Reference property back to (Default).

If you’re like me (lazy), chances are that you’ve tried to take shortcuts when refactoring BizTalk projects and run into the same trouble that I have.

What I’ve found is that if you open a BizTalk orchestration file in the Visual Studio XML viewer and made any changes to it (typical changes I would make here would be to cater for changes to names or namespaces), then the next time you try to open that file, it will only do so in a text viewer (you’ll see output like the below, this isn’t quite the same as an XML view, it certainly isn’t very helpful).

You can of course right click on the file and choose open with designer but this is an inconvience.

To fix this permanently, you will need to edit the .csproj project file (you can do this in visual studio by right clicking on the project, choosing unload, and then edit, or alternatively you can just open the file in notepad or some other text viewer).  Search for any XML elements named subtype and delete them.  This should fix your problem permanently.

I’m semi-convinced that I’ve had this problem with map files in the past as well.  While trying to reproduce this for the blog I’ve found that when I edited a map manually the subtype element did get added to the .csproj file but the map continued opening in the designer, weird.  Anyways, just remember as a rule that the subtype element is bad and you will want to get rid of it.

%d bloggers like this: