我想对我的视图模型进行单元测试,该模型可以进行wcf服务调用。
我的观点模型:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
});
}
}
我的服务客户端界面:
public interface IService
{
void LoadThisAndThat(EventHandler<ThisAndThatCompletedArgs> callback);
}
这是由一个使用实际生成的服务客户端代理进行调用的类实现的。
我的问题是:我如何进行单元测试,我的视图模型进行服务调用并使用返回的数据填充我的集合?
答案 0 :(得分:1)
要扩展Sheridan's answer - 你想测试什么?
我猜你真正感兴趣的是视图模型如何响应服务提供的数据。让我们稍微重新考虑您的代码,使其更加透明(我们真的已经完成了从服务方法的签名中删除EventHandler
委托):
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t =>
{
//Fill collections and so on
});
}
}
public interface IService
{
Result GetResult();
}
这是否回答了你的问题?没有!
即使您要模拟IService
的实现,线程的.NET实现也无法保证何时运行service.GetResult()
的调用,或者返回结果的时间查看模型。但是 - 我们是否有兴趣测试.NET线程实现?我猜不会。
如果您致力于测试,那么您必须将测试视为代码的一流消费者。为此,我们必须修改我们的代码,使其更适合测试。以下是两个:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load(bool runAync = true)
{
if (runAync)
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t => SetResults(t.Result));
else SetResults(service.GetResult());
}
private void SetResults(Result result)
{
//Fill collections and so on
}
}
这里我们为Load()
方法引入了一个布尔参数,默认为true
。在测试期间,我们使用false
调用它以确保结果同步处理,并且我们的视图模型的行为与我们对返回的数据的预期一致。
如果您不喜欢添加额外参数,可以将SetResults
方法公开,并将其视为测试期间的初始化步骤。
需要注意的是,我们不应该害怕改变公共实施以适应测试。
答案 1 :(得分:0)
只需实现一个返回TestService
类中某些数据的方法。目的是不来测试WCF服务是否有效,而是测试视图模型的工作方式。因此,我们创建了一个appears
的情况,好像服务工作正常...我们只是返回所需的数据,但无需调用实际的服务,这是其中一个我们试图避免的主要事情。
答案 2 :(得分:0)
这里的问题是异步调用回调。 回调模式已过时,请使用Task! 你可以做到
public Task<int> Load()
{
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
source.SetResult(e.Count);
});
return source.Task;
}
这样在你的测试中你可以(同步)
public void test()
{
var result=Load().Result;
}
任务很多很好!