扩展谢里登的答案-您要测试什么?
- 网络连接?
- 服务框架(例如 WCF)?
- 线程的.NET 实现?
我猜您真正感兴趣的只是您的视图模型如何响应服务提供的数据。让我们稍微重构您的代码以使其更加透明(我们所做的一切都是为了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 的实现,线程的 .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
方法公开,并将其视为测试期间的初始化步骤。
要点是我们不应该害怕对公共实施进行更改以适应测试。