Publié par : yoannr | 17 juin 2011

Gestion des Exceptions, Unit Testing, MsTests

J‘aimerai avoir une fonction de ce type la pour tester mon code :

static void Throws<T>(Action action, string expectedMessage) where T : Exception

Malheureusement celle ci n’existe pas dans la collection Assert. J ai donc vu de part le net qu’il me fallait créer ma propre classe MyAssert avec cette méthode. Et tant qu’à faire je me suis dit que j’allais le faire en TDD.

Throws<T> va contenir des accès direct  à Assert, et par conséquent sera difficilement testable (encore que maintenant que j’ècris ce lignes je trouve que je me suis compliquée la vie, mais bon… Sourire )

Je me susi donc créer cette classe :

public class AssertAnswer
        {
            public bool Success { get; set; }
            public string Message { get; set; }
        }

et un fonction qui contiendrait le corps de ma logique :

public static AssertAnswer AssertAction<T>(Action action, string expectedMessage) where T : Exception
{
}

C’est cette fonction que je compte tester. J’écris donc mes tests :

private void ThrowNullReferenceException(string msg)
      {
          throw new NullReferenceException(msg);
      }
private void DoNotThrowException(string msg)
      {
          //do nothing
      }

[TestMethod]
        public void MyAssert_AssertAction_Exception_Awaited()
        {
            string msg = "test";
            var actual = MyAssert.AssertAction<System.NullReferenceException>(() => ThrowNullReferenceException(msg), msg);

            Assert.AreEqual(true, actual.Success);
            Assert.AreEqual(msg, actual.Message);
        }

[TestMethod]
        public void MyAssert_AssertAction_Different_Exception()
        {
            string msg = "test";
            var actual = MyAssert.AssertAction<System.ArgumentException>(() => ThrowNullReferenceException(msg), msg);

            Assert.AreEqual(false, actual.Success);
            Assert.AreEqual("A different Exception was thrown System.NullReferenceException.", actual.Message);
        }

[TestMethod]
        public void MyAssert_AssertAction_No_Exception()
        {
            string msg = "test";
            var actual = MyAssert.AssertAction<System.ArgumentException>(() => DoNotThrowException(msg), msg);

            Assert.AreEqual(false, actual.Success);
            Assert.AreEqual("Exception of type System.ArgumentException should be thrown.", actual.Message);
        }

Ces trois tests couvrent l’ensemble des cas de figure qui peuvent se passer.

Il ne reste plus qu’à écrire le code  de la fonction :

public static AssertAnswer AssertAction<T>(Action action, string expectedMessage) where T : Exception
       {
           AssertAnswer answer = new AssertAnswer();

           try
           {
               action.Invoke();

               answer.Success = false;
               answer.Message = string.Format("Exception of type {0} should be thrown.", typeof(T));
           }
           catch (T exc)
           {
               answer.Success = true;
               answer.Message = expectedMessage;
           }
           catch (Exception e)
           {
               answer.Success = false;
               answer.Message = string.Format("A different Exception was thrown {0}.", e.GetType());
           }

           return answer;
       }

Mes tests passent je peux continuer , et revenir a mon besoin initial , en réécrivant d’autres tests pour vraiment tester la fonction que je compte appeler plus tard :

[TestMethod]
       public void MyAssert_Throws_Exception_Awaited()
       {
           string msg = "test";
           MyAssert.Throws<System.NullReferenceException>(() => ThrowNullReferenceException(msg), msg);
       }

       [TestMethod]
       public void MyAssert_Throws_Different_Exception()
       {
           try
           {
               string msg = "test";
               MyAssert.Throws<System.ArgumentException>(() => ThrowNullReferenceException(msg), msg);

               Assert.Fail();
           }
           catch (Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException e)
           {

           }
       }

       [TestMethod]
       public void MyAssert_Throws_No_Exception()
       {
           try
           {
               string msg = "test";
               MyAssert.Throws<System.ArgumentException>(() => DoNotThrowException(msg), msg);

               Assert.Fail();
           }
           catch (Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException e)
           {

           }
       }

 

et ensuite le code le fonction pour réussir ces tests :

public static void Throws<T>(Action action, string expectedMessage) where T : Exception
       {
           AssertAnswer answer = AssertAction<T>(action, expectedMessage);

           Assert.IsTrue(answer.Success);
           Assert.AreEqual(expectedMessage, answer.Message);
       }

 

et voila, ma fonction est prête à être utilisé dans d’autres tests. Maintenant , il est vrai que j’aurais pu m’épargner la création de la fonction AssertAction et tester directement le code de ma fonction, mais que voulez vous, il faut bien débuter un jour et faire quelques erreurs.. d’ailleurs si vous en voyez d’autres n’hésitez pas..

++


Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Twitter picture

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Connexion à %s

Catégories

Suivre

Get every new post delivered to your Inbox.