0

我想对进行 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);
}

这是由一个类实现的,该类使用实际生成的服务客户端代理进行调用。

我的问题是:我怎样才能对我的视图模型进行服务调用并用返回的数据填充我的集合进行单元测试?

4

3 回答 3

1

扩展谢里登的答案-您要测试什么?

  • 网络连接?
  • 服务框架(例如 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方法公开,并将其视为测试期间的初始化步骤。

要点是我们不应该害怕对公共实施进行更改以适应测试。

于 2013-08-28T11:30:51.783 回答
0

TestService只需实现一个在您的类中返回一些数据的方法。目的不是测试 WCF 服务是否工作,而是测试视图模型是如何工作的。因此,我们创造了一种情况,appears好像服务运行良好......我们只是返回所需的数据,但不需要调用实际的服务,这是我们试图避免的主要事情之一。

于 2013-08-28T08:12:28.723 回答
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;
}

任务对很多事情都有好处!

于 2013-08-28T09:12:42.357 回答