RhinoMocks Тестирование метода обратного вызова
У меня есть прокси-класс службы, который делает асинхронный вызов службы. Я использую метод обратного вызова для передачи результатов обратно в мою модель представления.
Выполняя функциональное тестирование модели представления, я могу смоделировать прокси-сервер службы, чтобы гарантировать, что методы прокси-сервера вызываются, но как я могу гарантировать, что метод обратного вызова также вызывается?
С помощью 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 ответ
Немного поиграл с этим, и я думаю, что у меня есть то, что вы ищете. Сначала я покажу код 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
{
}
Вы заметите несколько вещей:
Я сделал твой обратный звонок внутренним. Вам нужно будет использовать атрибут InternalsVisisbleTo(), чтобы ваша сборка ViewModel выставляла внутренние компоненты для ваших модульных тестов (я не в восторге от этого, но в редких случаях, как это).
Я использую Rhino.Mocks "Do" для выполнения обратного вызова всякий раз, когда вызывается GetData. Он не использует обратный вызов, но это скорее интеграционный тест. Я предполагаю, что у вас есть модульный тест ViewModel, чтобы убедиться, что реальный обратный вызов, переданный в GetData, выполняется в соответствующее время.
Очевидно, что вы захотите создать объекты mock/stub Entity и ServiceError, а не просто создавать новые, как я.