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:
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 Transform
1 = 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

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