BizMock

Framework for quick testing of BizTalk orchestrations, maps and more.
Create unit tests with regular C# MS tests, enhanced with a fluent interface API and a DDD approach.
Use its mocking capabilities, to avoid relying on dependent infraestructure like web services or DBs.

A sample scenario:

bizmocksample.png
Figure: an orchestration receives a request with a postal code field which is mapped to a city, then calls a weather service that returns a forecast report message, which is in turn mapped to a message that goes to the outbound port.

To test the above orchestration write a test like this using MSTest:

using Microsoft.Services.Spain.BizMock.Framework;

namespace BizMocklLabProjectTest
{
    [TestClass]
    public class Tests
    {
        public Tests()
        {
        }

        [TestMethod]
        [DeploymentItem("FileInstances")] //this is the folder where all the file message instances will be stored
        public void OrchestrationTest()
        {
            //First we set some expectations on messages
            Expectation.WeatherServiceRequest.City = "Barcelona";
            Expectation.Response.Report = "partially cloudy";
            Expectation.Response.City = "Barcelona";

            //We begin by sending to the Inbound receive location, a request (that we get from a file instance) changing its postal code value to 8001.
            At.ReceiveLocation(Port.InboundPort).Send(FileInstance.InboundReq.ChangePostalCodeTo("08001")).Then
            (
                //Then we expect an outgoing message, at the weather service, that should verify the _WeatherServiceRequest_ expectation ( City = "Barcelona" )
                At.SolicitResponsePort(Port.WeatherService).Expect.One.MessageLike(Expectation.WeatherServiceRequest).Then
                (
                    //Then we simulate (mock) the service response, by returning a message (that we get from a file instance)  changing its weather report value to "partially cloudy"
                    At.SolicitResponsePort(Port.WeatherService).Return(FileInstance.WeatherServiceResp.ChangeWeatherReportTo("partially cloudy")).Then
                    (
                        //Then we expect an oubound message that should verify the _Response_ expectation
                        At.SendPort( Port.Outbound ).Expect.One.MessageLike( Expectation.Response ),
                        //We also expect, no event log errors in the BizMock Event source. 
                        At.EventLog( EventLog.BizMock ).Expect.Nothing
                    )
                )
            ).Execute();

            string errors;
            Assert.IsTrue( BizMockery.Instance.VerifyAllExpectationsHaveBeenMet(10, out errors), errors );
        }
   }
}
No arcane processing code, no xpaths or file paths strings, no need to rely on dependent infraestructure like web services or DBs; Only write code at the domain abstraction level.
By using a Domain Driven Design approach, and a fluent interface style of programming, we will have a code easier to write and read.

But before writing this test, we should create some code artifacts referenced by the test. This artifacts are normal c# objects that represents the artifacts used by our orchestration like ports, messages, databases etc.
Once the artifacts are defined, we should be able to write tests faster, with a higher level of abstractions.

creating artifacts (ports, message expectations, maps ...):

This class exposes several message verifiers to verify outgoing messages:
{code:c#}
public class Expectation
{
public static void Reset()
{
Request.Reset();
}

//Expectation artifacts to assert received or sent message ( verify schema or content )
public static RequestVerifier Request = new RequestVerifier();
public static ResponseVerifier Response = new ResponseVerifier();
public static WeatherServiceRequestVerifier WeatherServiceRequest = new WeatherServiceRequestVerifier();
public static WeatherServiceResponseVerifier WeatherServiceResponse = new WeatherServiceResponseVerifier();

}
{code:c#}
This class exposes several file instance to send messages to receive locations or to simulate responses from solicit response ports:
{code:c#}

public class FileInstance
{
public static void Reset()
{
}

//File message instances artifacts ( sample messages to mock requests and responses )
public static RequestFile InboundReq = new RequestFile("Request.xml");
public static WeatherServiceResponse WeatherServiceResp = new WeatherServiceResponse("WeatherServiceResp.xml");
}
*This class representsd a map to test message transformations:*
public class Map
{
public static void Reset()
{
}

//Map artifacts to test maps
public static MapArtifact Transform1 = new MapArtifact( BizMockery.Instance.BizMockDirectory, new BizMockLabProject.Transform1() );
}
*This class exposes port artifacts like receive locations where we can send messages
public class Port
{
public static void Reset()
{
}

//Port artifacts represent receive and send port where we can send and return message instances or verify message expectations
public static ReceiveLocationArtifact InboundPort = new ReceiveLocationArtifact("rclRequest", 60); //rclRequest is the name of the receive location as specified in BizTalk binding
public static SolicitResponsePortArtifact WeatherService = new SolicitResponsePortArtifact("WeatherServicePort"); // WeatherServicePort is the name of the solicit response port as specified in BizTalk binding
public static SendPortArtifact Outbound = new SendPortArtifact("OutboundPort"); // OutboundPort is the name of the outbound send port as specified in BizTalk binding

}
*This class exposes event logs used tocheck the presence of especial events like  errors, warnings or info:*

public class EventLog
{
public static void Reset()
{
}

//Represent an event log filtered by a event source.
public static EventLogArtifact BizMock = new EventLogArtifact("Application", "BizMock");
}

}

 The following list shows all the standard Bizmock artifact types that we can expose:
** One way Receive location
** One way send port
** Request Response receive location
** Solicit Response port
** Message instance
** Message verifier
** Map
** Database
** Event log
** Business rule
** Pipeline 

!! How to customize artifacts so that there are more domain specific:
You can use the default Bizmock artifacts types, or create your own artifact types by inheritance from the bizmock types 

For example the following code shows the usage of a custom file message instance artifact called RequestFile that represents an inbound message, but enhanced with a specific behaviour, that allows changing the message postal code value during test execution.

public class FileInstance
{
...
public static RequestFile InboundReq = new RequestFile("Request.xml");
...
FileInstance.InboundReq.ChangePostalCodeTo("08001")
...

It inherits from _FileArtifact_ and leverages the _FindXmlNodeAndReplace_ base class method to implement its behaviour:
public class RequestFile : FileArtifact
{
string _file;
public RequestFile( string file) : base( file )
{
_file = file;
}

public string ChangePostalCode(string newPostalCode)
{
return this.FindXmlNodeAndReplace("/*[local-name()'Request' and namespace-uri()'http://BizMockLabProject.Request']/*[local-name()'PostalCode' and namespace-uri()'']", newPostalCode);
}
}

Expectation.WeatherServiceRequest is a message verifier used to assert, if a message meets the _WeatherServiceReq_ schema and can also be initialized to assert the value of a City field  

Expectation.WeatherServiceRequest.City = "Barcelona"
{code:c#}

It inherits from XmlMessageVerifierArtifact and leverages the ExpectedValue base class method to implement its behaviour
public class WeatherServiceRequestVerifier : XmlMessageVerifierArtifact
    {
        public WeatherServiceRequestVerifier()
        {
            this.Schema = new BizMockLabProject.WeatherServiceReq().Schema;
        }

        public string City
        {
            set
            {
                this.ExpectedValue("/*[local-name()'WeatherServiceRequest' and namespace-uri()'http://BizMockLabProject.WeatherServiceReq']/*[local-name()'City' and namespace-uri()'']", value);
            }
        }
    }

As you can see the effort of creating artifacts is worthwhile, especially if you reuse artifacts across several tests. In other words, more tests you write for a given solution, more time you will gain per test.
Fortunately it's not a big deal as you have seen; just declare default bizmock artifact types, or create your own artifact types by inhereting from Bizmock artifact types, to add your specific behaviour.

How verify a message instance

MessageVerifier allows you to quickly verify if a specific file instance message meets a message verifier.
This kind of tests are useful to quickly detect all the file instance messages, that have gone out of sync with their schemas.
 [TestMethod]
 [DeploymentItem("FileInstances")]
 public void RequestSchemaTest()
 {
   string myPostalCode = "28850";
   Expectation.Request.PostalCode = myPostalCode;
   Assert.IsTrue( MessageVerifier.Verify(FileInstance.InboundReq.ChangePostalCodeTo(myPostalCode), Expectation.Request));
  }

How to quickly test a map

The MapVerifier.Verify method allows to test a Map in a very straightforward way. Pass the input message Instance, the map artifact you want to test, and a message verifier to verify the transformed message meets your expectations
  [TestMethod]
  [DeploymentItem("FileInstances")]
  public void Transform_1Test()
  {
      Expectation.WeatherServiceRequest.City=" Barcelona";
      Assert.IsTrue(MapVerifier.Verify(FileInstance.InboundReq.ChangePostalCodeTo("08001"), Maps.Transform_1, Expectation.WeatherServiceRequest));
   }

Design

bzmockdesign.png

A fluent interface http://www.martinfowler.com/bliki/FluentInterface.html allows you to code as a Domain Specific Language.
Using the BizMock fluent interface we specify expectations (events or conditions expected to happen) on artifacts ( ports, databases etc).
When this expectations are verified they trigger actions to create new expectations, or act upon the file system ( for example, to create a mocked response message), or to invoke the Bizmock receive adapter ( to send a message to a receive port), or to call the BizTalk WMI management classes, or any WMI provider.

Main advantages of using Bizmock:

  • Rapid testing of Biztalk scenarios ( no more excuses to not test biztalk code)
  • No need to leave the Visual Studio IDE
  • We use regular Visual Studio C# Unit Tests code ( no puzzling xml) .
  • Type Safe API
  • Favors agile iterative development cycles with continous Integration.
  • No need to rely on real implementations of dependent infraestructure like web services, Databases, etc. ( isolated on the developer machine or build server )
  • Increasead level of abstraction thanks to its Domain Driven Design approach and fluent interface.
  • Rapid and guided development thanks to intelisense and its fluent interface API.
  • Reusability of domain artifacts across tests, like ports, messages, verifiers etc.
  • Extensibility model to allow the creation of new artifacts, actions, and expectations types over time and reused across solutions
  • Leverages DDT ( Data Driven Test)

Next release wish list

  • Visual Studio Guidance automation to drive the test development
  • Wizards to auto generate solution specific artifacts
    • Create message verifier artifacts taking as input a message schema, then selecting the fields when want to assert
    • Create message instance artifacts taking as input a message schema, then selecting the fields when want to modify
    • Create a database artifact by auto generating the connection string, and sql commands
    • etc.
  • Addins to change bindings to use BizMock adapter
  • Integration wirth functional testing tools like FIT
  • Mocking of port transport context properties
Last edited Jul 29 at 2:56 AM by haddock747, version 154

 

Want to leave feedback?
Please use Discussions or Reviews instead.

Updating...
© 2006-2009 Microsoft | About CodePlex | Privacy Statement | Terms of Use | Code of Conduct | Advertise With Us | Version 2009.10.27.15987