2010-05-28 17 views
0

J'ai une classe de proxy de service qui effectue un appel asyn à l'opération de service. J'utilise une méthode de rappel pour renvoyer les résultats à mon modèle de vue.RhinoMocks Méthode de rappel de test

En effectuant des tests fonctionnels du modèle de vue, je peux simuler le proxy de service pour m'assurer que les méthodes sont appelées sur le proxy, mais comment puis-je m'assurer que la méthode de rappel est également appelée? Avec RhinoMocks, je peux tester que les événements sont gérés et que l'événement déclenche des événements sur l'objet simulé, mais comment puis-je tester les rappels?

ViewModel:

public class MyViewModel 
{ 
    public void GetDataAsync() 
    { 
     // Use DI framework to get the object 
     IMyServiceClient myServiceClient = IoC.Resolve<IMyServiceClient>(); 
     myServiceClient.GetData(GetDataAsyncCallback); 
    } 

    private void GetDataAsyncCallback(Entity entity, ServiceError error) 
    { 
     // do something here... 
    } 

} 

ServiceProxy:

public class MyService : ClientBase<IMyService>, IMyServiceClient 
{ 
    // Constructor 
    public NertiAdminServiceClient(string endpointConfigurationName, string remoteAddress) 
     : 
      base(endpointConfigurationName, remoteAddress) 
    { 
    } 

    // IMyServiceClient member. 
    public void GetData(Action<Entity, ServiceError> callback) 
    { 
     Channel.BeginGetData(EndGetData, callback); 
    } 

    private void EndGetData(IAsyncResult result) 
    { 
     Action<Entity, ServiceError> callback = 
      result.AsyncState as Action<Entity, ServiceError>; 

     ServiceError error; 
     Entity results = Channel.EndGetData(out error, result); 

     if (callback != null) 
      callback(results, error); 
    } 
} 

Merci

Répondre

1

joué avec cela un peu et je pense que je peux avoir ce que vous cherchez. Tout d'abord, je vais afficher le code MSTest je l'ai fait pour vérifier:

[TestClass] 
public class UnitTest3 
{ 
    private delegate void MakeCallbackDelegate(Action<Entity, ServiceError> callback); 

    [TestMethod] 
    public void CallbackIntoViewModel() 
    { 
     var service = MockRepository.GenerateStub<IMyServiceClient>(); 
     var model = new MyViewModel(service); 

     service.Stub(s => s.GetData(null)).Do(
      new MakeCallbackDelegate(c => model.GetDataCallback(new Entity(), new ServiceError()))); 
     model.GetDataAsync(null); 
    } 
} 

public class MyViewModel 
{ 
    private readonly IMyServiceClient client; 

    public MyViewModel(IMyServiceClient client) 
    { 
     this.client = client; 
    } 

    public virtual void GetDataAsync(Action<Entity, ServiceError> callback) 
    { 
     this.client.GetData(callback); 
    } 

    internal void GetDataCallback(Entity entity, ServiceError serviceError) 
    { 

    } 
} 

public interface IMyServiceClient 
{ 
    void GetData(Action<Entity, ServiceError> callback); 
} 

public class Entity 
{ 
} 

public class ServiceError 
{ 
} 

Vous remarquerez un certain nombre de choses:

  1. J'ai fait votre rappel interne. Vous aurez besoin d'utiliser l'attribut InternalsVisisbleTo() pour que votre assemblage ViewModel expose des internes à vos tests unitaires (je ne suis pas fou de ça, mais ça arrive dans de rares cas comme ça). J'utilise Rhino.Mocks "Do" pour exécuter le rappel à chaque appel de GetData. Il n'utilise pas le rappel fourni, mais c'est vraiment plus un test d'intégration. Je suppose que vous avez un test d'unité ViewModel pour vous assurer que le callback réel transmis à GetData est exécuté au moment opportun.

  2. De toute évidence, vous aurez besoin de créer des objets Entité et ServiceError faux/stub au lieu de simplement vous lancer comme je l'ai fait.

+0

Pourriez-vous indiquer comment rendre la méthode interne visible pour le projet de test unitaire. merci – joblot

+0

j'ai travaillé comment rendre la méthode interne visible. pourriez-vous s'il vous plaît expliquer ce que Do faire et pourquoi nous avons créé un Stud pour le service. merci – joblot

+0

Ceci est juste un test unitaire pour votre ViewModel. Par conséquent, toutes les dépendances extérieures sont mocked/stubbed. La méthode "Do" indique à Rhino.Mocks d'exécuter un morceau de code spécifique à chaque fois qu'une méthode est appelée. J'ai utilisé "Do" pour que votre ViewModel puisse appeler "GetDataAsync" et reçoive également un rappel - tout cela pendant le test. Tester si le service exécute des rappels est effectué dans le cadre d'un test unitaire de la classe Service. – PatrickSteele