Question

J'ai une classe proxy de service qui fait appel asyn au fonctionnement du service. J'utilise une méthode de rappel pour passer résultats à mon modèle de vue.

Faire des tests fonctionnels du modèle de vue, je peux se moquer de proxy de service pour assurer les méthodes sont appelées sur le proxy, mais comment puis-je faire en sorte que la méthode de rappel est appelée ainsi?

Avec RhinoMocks je peux vérifier que les événements sont traités et les événements soulèvent des événements sur l'objet moqué, mais comment puis-je tester callbacks?

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

Était-ce utile?

La solution

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 vérifier ceci:

[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 que quelques petites choses:

  1. J'ai fait votre rappel interne. Vous aurez besoin d'utiliser l'attribut InternalsVisisbleTo () de sorte que votre ViewModel expose l'assemblage à vos internes des tests unitaires (je ne suis pas fou à ce sujet, mais il arrive dans de rares cas comme celui-ci).

  2. J'utilise Rhino.Mocks « Do » pour exécuter le rappel lorsque le GetData est appelé. Il n'utilise pas le rappel fourni, mais cela est vraiment plus d'un test d'intégration. Je suppose que vous avez un test unitaire ViewModel pour vous assurer que le rappel réel passé pour GetData est exécuté au moment opportun.

  3. De toute évidence, vous aurez envie de créer stub mock / objets Entity et ServiceError au lieu de simplement new'ing jusqu'à comme je l'ai fait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top