2016-11-23 2 views
4

J'ai un test de test défaillant qui dépend d'un module externe. Je souhaite utiliser Rhino Mock pour générer un rapport sur les fonctions appelées.Utilisez Rhino Mock pour signaler la fonction qui a été appelée

J'ai créé un exemple minimal qui illustre mon problème:

using NUnit.Framework; 
using Rhino.Mocks; 
using System; 

namespace StackOverflow_namespace 
{ 
    public interface IUsefulService 
    { 
     object HiddenAmongManyCalls(); 
    } 

    public class ThirdPartyBase 
    { 
     private int a = 42; 

     public ThirdPartyBase(IUsefulService service) 
     { 
      object liveFastDieYoung = service.HiddenAmongManyCalls(); 
      liveFastDieYoung.Equals(a); 
     } 
    } 

    public class MyParty : ThirdPartyBase 
    { 
     public MyParty(IUsefulService service) : base(service) 
     { 

     } 
    } 


    [TestFixture] 
    class StackOverflow 
    { 
     [Test] 
     public void Hypothetical() 
     { 
      IUsefulService service = MockRepository.GenerateMock<IUsefulService>(); 

      try 
      { 
       var party = new MyParty(service); 
      } 
      catch(Exception e) 
      { 
       string[] calls = MagicallyGetTheCallsThatWereMadeToTheMock(); 
       foreach(var call in calls) 
       { 
        //with my visual studio testrunner for nunit 3 I can investigate stored console output 
        Console.WriteLine(call); 
       } 
       Assert.Fail("Excpexted no exception but was '" + e.GetType().Name + "': " + e.Message); 
      } 
     } 

     private string[] MagicallyGetTheCallsThatWereMadeToTheMock() 
     { 
      return new[] 
      { 
       "This is where I am lost, I do not know how to get the calls from the repository." 
      }; 
     } 
    } 
} 

J'ai essayé de trouver quelque chose en ligne sans succès.

Est-ce que Rhino Mocks enregistre tous les appels et puis-je accéder à cette liste?

Edit:

Une tentative de vérifier les attentes ne fonctionne pas depuis que je suis à la recherche d'appels je ne m'y attendais.

Je pourrais construire une liste d'appels en utilisant GetArgumentsForCallsMadeOn. Je peux réfléchir sur l'interface. J'ai commencé sur une méthode pour cela mais je ne vois pas comment je peux convertir un MethodInfo en Action<T>.

private IEnumerable<string> GetCallsList<Interface>(Interface rhinomock) 
{ 
    Type interfaceType = typeof(Interface); 
    List<MethodInfo> interfaceMethodInfos = new List<MethodInfo>(); 
    List<string> returnInfos = new List<string>(); 
    StringBuilder callbuilder = new StringBuilder(); 

    foreach (var property in interfaceType.GetProperties()) 
    { 
     interfaceMethodInfos.Add(property.GetGetMethod()); 
     interfaceMethodInfos.Add(property.GetSetMethod()); 
    } 
    foreach (var method in interfaceType.GetMethods()) 
    { 
     interfaceMethodInfos.Add(method); 
    } 

    foreach (var methodinfo in interfaceMethodInfos) 
    { 
     Action<Interface> magic = null; //convert methodinfo into action - still missing 
     var calls = rhinomock.GetArgumentsForCallsMadeOn(magic); //magic is currently null, here be crash 
     foreach (var call in calls) 
     { 
      bool more = false; 
      callbuilder.Clear().Append(interfaceType.Name).Append('.').Append(methodinfo.Name).Append('('); 
      foreach (var parameter in call) 
      { 
       if (more){ callbuilder.Append(", "); } 
       if (null == parameter) { callbuilder.Append("<null>"); } 
       else { callbuilder.Append(parameter.ToString()); } 
       more = true; 
      } 
      callbuilder.Append(')'); 
      string callInfo = callbuilder.ToString(); 
      returnInfos.Add(callInfo); 
     } 
    } 
    return returnInfos; 
} 
+0

Oui rhinomocks enregistre tous les appels de méthode. Vous pouvez vérifier leur exécution à l'aide de AssertWasCalled. –

+0

@OldFox Je peux vérifier tout ce que j'attends mais avec un appel comme celui ci-dessus où quelque chose est fait que je ne m'attends pas à vouloir créer un rapport qui me montre ce qui s'est passé. Je ne pense pas que VerifyAllExpectations ferait ça pour moi. – Johannes

+2

Dans les UT, vous devez vérifier un comportement attendu. C'est une mauvaise pratique d'espionner tous les appels. 'VerifyAllExpectations' ne résoudra pas votre problème. Lorsque vous ne voulez pas autoriser des appels inattendus, vous devez utiliser Strict Mock (aujourd'hui, ce type de simulation est considéré comme une mauvaise pratique ...). Si vous voulez toujours avoir un accès aux enregistrements: utilisez la reflexion ou téléchargez le code source de rhinomocks et faites quelques changements .... –

Répondre

2

J'ai été capable d'utiliser la réflexion pour obtenir la sortie que je voulais. Voici l'exemple minimal où le test échoue et la sortie contient tous les appels de méthodes.

using NUnit.Framework; 
using Rhino.Mocks; 
using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.Text; 

namespace StackOverflow_namespace 
{ 
    public interface IUsefulService 
    { 
     object HiddenAmongManyCalls(); 
     string TestCall2(string arg1, int arg2); 
     string FULLACCESS { get; set; } 
     string READONLY { get; } 
    } 

    public class ThirdPartyBase 
    { 
     private int a = 42; 

     public ThirdPartyBase(IUsefulService service) 
     { 
      service.TestCall2("callA", 1); 
      service.TestCall2("callB", 1); 
      object liveFastDieYoung = service.HiddenAmongManyCalls(); 
      service.TestCall2("callA", 2); 
      service.TestCall2("callB", 2); 
      var a = service.FULLACCESS; 
      var b = service.READONLY; 
      service.FULLACCESS = "some"; 
      liveFastDieYoung.Equals(a); 
     } 
    } 

    public class MyParty : ThirdPartyBase 
    { 
     public MyParty(IUsefulService service) : base(service) 
     { 

     } 
    } 


    [TestFixture] 
    class StackOverflow 
    { 
     [Test] 
     public void Hypothetical() 
     { 
      IUsefulService service = MockRepository.GenerateMock<IUsefulService>(); 

      try 
      { 
       var party = new MyParty(service); 
      } 
      catch (Exception e) 
      { 
       var calls = GetCallsList(service); 
       foreach (var call in calls) 
       { 
        //with my visual studio testrunner for nunit 3 I can investigate stored console output 
        Console.WriteLine(call); 
       } 
       Assert.Fail("Excpexted no exception but was '" + e.GetType().Name + "': " + e.Message); 
      } 
     } 

     private IEnumerable<string> GetCallsList<Interface>(Interface rhinomock) 
     { 
      Type interfaceType = typeof(Interface); 
      List<MethodInfo> interfaceMethodInfos = new List<MethodInfo>(); 
      List<string> returnInfos = new List<string>(); 
      StringBuilder callbuilder = new StringBuilder(); 

      foreach (var property in interfaceType.GetProperties()) 
      { 
       AddMethodInfoIfValid(interfaceMethodInfos, property.GetGetMethod()); 
       AddMethodInfoIfValid(interfaceMethodInfos, property.GetSetMethod()); 
      } 
      foreach (var method in interfaceType.GetMethods()) 
      { 
       AddMethodInfoIfValid(interfaceMethodInfos, method); 
      } 

      foreach (var methodinfo in interfaceMethodInfos) 
      { 
       int paramcount = methodinfo.GetParameters().Length; 
       object[] args = new object[paramcount]; 
       Action<Interface> lambdacall = (i) => methodinfo.Invoke(i, args); 
       var calls = rhinomock.GetArgumentsForCallsMadeOn(lambdacall); 
       foreach (var call in calls) 
       { 
        bool more = false; 
        callbuilder.Clear().Append(interfaceType.Name).Append('.').Append(methodinfo.Name).Append('('); 
        foreach (var parameter in call) 
        { 
         if (more) { callbuilder.Append(", "); } 
         if (null == parameter) { callbuilder.Append("<null>"); } 
         else { 
          callbuilder 
           .Append('(').Append(parameter.GetType().Name).Append(")'") 
           .Append(parameter.ToString()).Append("'"); 
         } 
         more = true; 
        } 
        callbuilder.Append(')'); 
        string callInfo = callbuilder.ToString(); 
        returnInfos.Add(callInfo); 
       } 
      } 
      return returnInfos; 
     } 

     private static void AddMethodInfoIfValid(List<MethodInfo> interfaceMethodInfos, MethodInfo methodinfo) 
     { 
      if (null != methodinfo) 
      { 
       interfaceMethodInfos.Add(methodinfo); 
      } 
     } 
    } 
}