使用WCF服务调用测试视图模型

时间:2013-08-28 07:33:20

标签: c# wpf wcf unit-testing nunit

我想对我的视图模型进行单元测试,该模型可以进行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);
}

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

我的问题是:我如何进行单元测试,我的视图模型进行服务调用并使用返回的数据填充我的集合?

3 个答案:

答案 0 :(得分:1)

要扩展Sheridan's answer - 你想测试什么?

  • 网络连接?
  • 服务框架(例如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实现也无法保证何时运行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;
}

任务很多很好!