RhinoMocks Тестирование метода обратного вызова - PullRequest
0 голосов
/ 28 мая 2010

У меня есть прокси-класс службы, который выполняет асинхронный вызов службы. Я использую метод обратного вызова для передачи результатов обратно в мою модель представления.

Выполняя функциональное тестирование модели представления, я могу смоделировать прокси-сервер службы, чтобы гарантировать, что методы прокси-сервера вызываются, но как я могу гарантировать, что метод обратного вызова также вызывается?

С помощью RhinoMocks я могу проверить, что события обрабатываются и события генерируют события на макете объекта, но как я могу проверить обратные вызовы?

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);
    }
}

Спасибо

1 Ответ

1 голос
/ 28 мая 2010

Немного поигрался с этим, и я думаю, у меня может быть то, что вы ищете. Сначала я покажу код MSTest, который я сделал, чтобы проверить это:

[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
{
}

Вы заметите несколько вещей:

  1. Я сделал ваш обратный звонок внутренним. Вам нужно будет использовать атрибут InternalsVisisbleTo (), чтобы ваша сборка ViewModel выставляла внутренние компоненты для ваших модульных тестов (я не в восторге от этого, но в редких случаях, как это).

  2. Я использую Rhino.Mocks «Do» для выполнения обратного вызова всякий раз, когда вызывается GetData. Он не использует обратный вызов, но это скорее интеграционный тест. Я предполагаю, что у вас есть модульный тест ViewModel, чтобы убедиться, что реальный обратный вызов, переданный в GetData, выполняется в соответствующее время.

  3. Очевидно, что вы захотите создать объекты-заглушки / заглушки Entity и ServiceError, а не просто создавать новые, как я.

...