Testez unitairement vos maps Biztalk

Florian Caillaud
Publié par Florian
Catégorie : BizTalk
01/06/2018

Cet article fait suite à la présentation des tests unitaires sur les schémas XML. Nous allons nous attarder, cette fois-ci, sur les tests unitaires relatifs aux maps BizTalk. La philosophie reste la même : garantir la validité et la non-régression des transformations tout au long d’un projet.

Encore une fois, nous allons créer un projet BizTalk 2016 simple, comportant deux schémas et une map permettant la transformation du premier vers le second. Pour information, le fonctoïd Script permet de faire une concaténation « complexe » comme nous le verrons ensuite.

map unit test with biztalk project

Il faut, ensuite, aller dans les propriétés du projet BizTalk pour mettre à « True » l’option « Enable Unit Testing ».

activer les test unitaires BizTalk map

Cette action aura pour effet de faire hériter les différentes maps du projet de la classe Microsoft.BizTalk.TestTools.Mapper.TestableMapBase qui elle-même hérite de Microsoft.XLANGs.BaseTypes.TransformBase (donc on conserve bien toutes les propriétés initiales d’une map BizTalk).

Il est possible de vérifier le changement d’héritage en ouvrant le fichier C# associé à la map.

Une des limites de cette approche est que l’assembly Microsoft.Biztalk.TestTools n’est pas présente nativement sur la version Production de BizTalk Server. Il existe alors 2 solutions :

* Soit ajouter cette assembly sur son environnement de production

* Soit définir un profil Debug (avec l’option « Enable Unit Testing » à « True »), et un profil Release (avec l’option à « False »)

La deuxième solution étant, à mon sens, plus propre que la première.

Comme pour les tests unitaires appliqués aux schémas, nous allons ensuite proposer deux méthodes différentes pour tester une map au sein d’un projet de tests unitaires.

La première méthode teste l’exécution de la map en lui fournissant l’adresse du fichier source et celle du fichier à créer en sortie (avec leur type respectif, XML ou Natif). Il est également possible de choisir le type « Generate » pour générer la source.


[TestMethod]
public void Validate_Address1_To_Address2_FirstMethod()

{

  MapUnitTesting.Address1_To_Address2 map = new MapUnitTesting.Address1_To_Address2();
  map.ValidateInput = true;
  map.ValidateOutput = true;

  string strSourceSchema = @"..\..\..\Sample\Address1_example.xml";
  string strDestinationSchema = @"..\..\..\Sample\Address1_example_out.xml";

  map.TestMap(strSourceSchema,
  InputInstanceType.Xml,
  strDestinationSchema,
  OutputInstanceType.XML);
  Assert.IsTrue(File.Exists(strDestinationSchema));
}

Cette approche implique certaines limitations :

  • Pour chaque cas particulier de la map, il faut ajouter le fichier source correspondant.
  • Même s’il est possible de faire valider la source et la destination, la vérification des données du fichier produit en sortie sera à votre charge.La deuxième méthode utilise le Framework MTF (Map Test Framework) qui se trouve (ici). Ce Framework est assez simple d’utilisation. En effet, il suffit de copier le dossier de téléchargement, dézippé, à l’emplacement souhaité puis d’ajouter une référence, dans le projet de tests unitaires, vers l’assembly MapTestFramework.Common. La documentation du Framework est présente directement sur le site.

De façon très simple, il faut faire hériter notre classe de test de la classe MappingFixture. Dans ce cadre, les méthodes ExpectedPathBase, SourcePathBase et CreateMap doivent être implémentées (comme ci-dessous). Il est, ensuite, facile de tester beaucoup plus finement notre map.


        protected override string ExpectedPathBase
        {
            get
            {
                return @"..\..\..\Sample\Address1_example_out.xml";
            }
        }

        protected override string SourcePathBase
        {
            get
            {
                return @"..\..\..\Sample\Address1_example.xml";
            }
        }

        protected override IMapExecuter CreateMap()
        {
            return new TestableMapBaseMapExecuter(new Address1_To_Address2());
        }

        [TestMethod]
        public void Validate_Address1_To_Address2_SecondMethod_BaseTest()
        {
            base.ExecuteBaseTest();
        }

        [TestMethod]
        public void Validate_Address1_To_Address2_SecondMethod_AdditionalTest_Sex()
        {
            string[] inputs = new string[]  {
                                                "/*[local-name()='Address1' and namespace-uri()='https://MapUnitTesting']/*[local-name()='Person' and namespace-uri()='']/*[local-name()='Sex' and namespace-uri()='']",
                                                "/*[local-name()='Address1' and namespace-uri()='https://MapUnitTesting']/*[local-name()='Person' and namespace-uri()='']/*[local-name()='FirstName' and namespace-uri()='']",
                                                "/*[local-name()='Address1' and namespace-uri()='https://MapUnitTesting']/*[local-name()='Person' and namespace-uri()='']/*[local-name()='LastName' and namespace-uri()='']"
                                            };
            string[] outputs = new string[] { "/*[local-name()='Address2' and namespace-uri()='https://MapUnitTesting']/*[local-name()='Name' and namespace-uri()='']" };

            MapTestCases collection = new MapTestCases(inputs,outputs);

            collection.AddTestCase(
                new string[] { "Male", "Florian", "CAILLAUD" }, new string[] { "Mr Florian CAILLAUD" }
                );

            collection.AddTestCase(
                new string[] { "Female", "Hao", "WU" }, new string[] { "Mme Hao WU" }
                );

            base.ExecuteMapTest(collection);
        }

Dans ce cas, nous fournissons, à travers les méthodes ExpectedPathBase et SourcePathBase, une base (template) d’un fichier source et d’un fichier destination.
Il est alors possible, en utilisant la méthode ExecuteBaseTest, de tester simplement (comme pour la première méthode) notre map.
Mais, comme le montre le test Validate_Address1_To_Address2_SecondMethod_AdditionalTest_Sex, il est possible, grâce aux chemins XPath, de rendre paramétrable certains champs. A partir de cela, le Framework permet de donner une liste de paramètres en entrée et une liste des valeurs attendues en sortie.
On peut alors tester la concaténation « complexe » de la map qui vise à réunir, au sein d’un même champ, la civilité (décidée en fonction du sexe), le prénom et le nom d’une personne.
Ce Framework possède d’autres fonctionnalités, qui ne sont pas détaillées dans cet article. Cela permet de mettre en place tout un éventail de tests unitaires autours des maps BizTalk.

Ces deux types de tests unitaires vous fournissent un moyen simple et généralement assez efficace de garantir la validité et la non-régression de vos transformations Biztalk.