我有一个服务代理类,它使asyn调用服务操作。我使用回调方法将结果传递回我的视图模型。
对视图模型进行功能测试,我可以模拟服务代理以确保在代理上调用方法,但是如何确保调用回调方法呢?
使用RhinoMocks,我可以测试事件是否被处理以及模拟对象上的事件引发事件,但我如何测试回调?
视图模型:
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);
}
}
由于
答案 0 :(得分: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程序集就会暴露你的单元测试的内部结构(我对此并不是很疯狂,但在极少数情况下会发生这种情况)。
每当调用GetData时,我都会使用Rhino.Mocks“Do”来执行回调。它没有使用提供的回调,但这实际上更像是一个集成测试。我假设您已经进行了ViewModel单元测试,以确保传入GetData的实际回调在适当的时间执行。
显然,您需要创建模拟/存根实体和ServiceError对象,而不是像我一样新建。