Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
模型-视图-视图模型&;WCF-WCF是模型吗?_Wcf_Mvvm_Stress Testing - Fatal编程技术网

模型-视图-视图模型&;WCF-WCF是模型吗?

模型-视图-视图模型&;WCF-WCF是模型吗?,wcf,mvvm,stress-testing,Wcf,Mvvm,Stress Testing,我只是在学习Model/View/ViewModel模式及其变体(DataModel/View/ViewModel或Model/View/Presenter) 我想知道的是:如果我将此模式用于WCF服务,该服务是模型(DataModel),还是需要一个单独的模型来封装WCF服务层 当我使用WCF作为数据模型时,如果不模拟整个WCF服务,我的ViewModel是不可测试的,因为对WCF的调用需要管理连接。此ViewModel中的调用如下所示: List<Sam.Alyza.WcfInterf

我只是在学习Model/View/ViewModel模式及其变体(DataModel/View/ViewModel或Model/View/Presenter)

我想知道的是:如果我将此模式用于WCF服务,该服务是模型(DataModel),还是需要一个单独的模型来封装WCF服务层

当我使用WCF作为数据模型时,如果不模拟整个WCF服务,我的ViewModel是不可测试的,因为对WCF的调用需要管理连接。此ViewModel中的调用如下所示:

List<Sam.Alyza.WcfInterface.Website> rc = null;
Service<Sam.Alyza.WcfInterface.IServiceWebsites>.Use(alyzaSvc =>
{
  rc = new List<Sam.Alyza.WcfInterface.Website>(alyzaSvc.GetSites());
});
List<Sam.Alyza.WcfInterface.Website> rc = new List<Sam.Alyza.WcfInterface.Website>(_datamodel.GetSites());
interface IClientFactory
{
    TClient CreateClient<TClient>();
}

class ClientFactory : IClientFactory
{
    TClient CreateClient<TClient>() 
    {
       var channelFactory = new ChannelFactory<TClient>("AlyzaServiceEndpoint");
       var proxy = (TClient)channelFactory.CreateChannel();
       return proxy;
    }
}

public ViewModel 
{
    public ViewModel(IClientFactory clientFactory)
    {
       _clientFactory = clientFactory;
    }

    private void DoWcfStuff()
    {
        using (var proxy = _clientFactory.CreateClient<IClientChannel>())
        {
           var result = proxy.GetThings();
        }
    }
}

public ViewModelTests
{
    public void Setup()
    {
       _mockFactory = new MockClientFactory();
       _viewModel = new ViewModel(_mockFactory);
    }

    [Test]
    public void Test() 
    {
       var testResult = new Result();
       var mockClient = _mockFactory.CreateClient<IClientChannel>();

       mockClient.SetResultForGetThings(testResult);

       // put the viewmodel through its paces.
    }

    private class MockClientFactory : IClientFactory
    {
        MockClient _mockClient;

        public MockClientFactory()
        {
          _mockClient = new MockClient();
        }

        public TClient CreateClient<TClient>()
        {
           if (typeof(TClient) == typeof(IClientChannel))
           {
              return _mockClient;
           }
        }
    }

    private class MockClient : IClientChannel
    {
        void SetupGetThingsResult(Result result)
        {
           _result = result;
        }

        Result GetThings() 
        {
           return _result;
        }
    }
}
List rc=null;
Service.Use(alyzaSvc=>
{
rc=新列表(alyzaSvc.GetSites());
});
为了使ViewModel可测试,我尝试添加一个单独的数据模型来抽象WCF连接。在此之后,ViewModel是可测试的,调用如下所示:

List<Sam.Alyza.WcfInterface.Website> rc = null;
Service<Sam.Alyza.WcfInterface.IServiceWebsites>.Use(alyzaSvc =>
{
  rc = new List<Sam.Alyza.WcfInterface.Website>(alyzaSvc.GetSites());
});
List<Sam.Alyza.WcfInterface.Website> rc = new List<Sam.Alyza.WcfInterface.Website>(_datamodel.GetSites());
interface IClientFactory
{
    TClient CreateClient<TClient>();
}

class ClientFactory : IClientFactory
{
    TClient CreateClient<TClient>() 
    {
       var channelFactory = new ChannelFactory<TClient>("AlyzaServiceEndpoint");
       var proxy = (TClient)channelFactory.CreateChannel();
       return proxy;
    }
}

public ViewModel 
{
    public ViewModel(IClientFactory clientFactory)
    {
       _clientFactory = clientFactory;
    }

    private void DoWcfStuff()
    {
        using (var proxy = _clientFactory.CreateClient<IClientChannel>())
        {
           var result = proxy.GetThings();
        }
    }
}

public ViewModelTests
{
    public void Setup()
    {
       _mockFactory = new MockClientFactory();
       _viewModel = new ViewModel(_mockFactory);
    }

    [Test]
    public void Test() 
    {
       var testResult = new Result();
       var mockClient = _mockFactory.CreateClient<IClientChannel>();

       mockClient.SetResultForGetThings(testResult);

       // put the viewmodel through its paces.
    }

    private class MockClientFactory : IClientFactory
    {
        MockClient _mockClient;

        public MockClientFactory()
        {
          _mockClient = new MockClient();
        }

        public TClient CreateClient<TClient>()
        {
           if (typeof(TClient) == typeof(IClientChannel))
           {
              return _mockClient;
           }
        }
    }

    private class MockClient : IClientChannel
    {
        void SetupGetThingsResult(Result result)
        {
           _result = result;
        }

        Result GetThings() 
        {
           return _result;
        }
    }
}
List rc=新列表(_datamodel.GetSites());
问题:现在需要测试的大部分代码都已经转移到了数据模型中,这同样需要测试WCF。ViewModel中剩下的是一个薄壳,可以进行测试。但是由于主代码移到了数据模型中,因此测试ViewModel是毫无用处的


因此,在我看来,使用WCF向View/ViewModel应用程序添加单独的数据模型层确实增加了很多工作,但可测试性并没有得到任何改善。

Woot,经过两天的努力,我找到了一个我可以接受的解决方案:

如上面的代码示例所示,我使用这个helper类来管理我的WCF连接(因为正确处理了关闭与中止):

public委托void-UseServiceDelegate(T-proxy);
公共静态类服务
{
公共静态通道工厂_ChannelFactory;
公共静态无效使用(UseServiceDelegate代码块)
{
如果(_channelFactory==null)
_channelFactory=新的channelFactory(“AlyzaServiceEndpoint”);
IClientChannel代理=(IClientChannel)_channelFactory.CreateChannel();
布尔成功=假;
尝试
{
代码块((T)代理);
proxy.Close();
成功=真实;
}
最后
{
如果(!成功)
{
proxy.Abort();
}
}
}
}
如我的问题所示,这是在我的ViewModel中使用此类的方式:

Service<Sam.Alyza.WcfInterface.IServiceWebsites>.Use(alyzaSvc =>
{
  rc = new List<Sam.Alyza.WcfInterface.Website>(alyzaSvc.GetSites());
});
Service.Use(alyzaSvc=>
{
rc=新列表(alyzaSvc.GetSites());
});
要模拟WCF接口,我需要创建并托管一个模拟WCF服务,更改所有连接字符串。只需添加一些测试就可以完成大量工作

我找到了一个更简单的方法: 创建实现接口的模拟服务很简单:

public class MockWebsiteService : WcfInterface.IServiceWebsites
{
  internal List<Sam.Alyza.WcfInterface.Website> _websites = new List<Sam.Alyza.WcfInterface.Website>();
  internal int _GetSitesCallCount;

  IEnumerable<Sam.Alyza.WcfInterface.Website> Sam.Alyza.WcfInterface.IServiceWebsites.GetSites()
  {
    _GetSitesCallCount++;
    return _websites;
  }
}
公共类MockWebsiteService:WcfInterface.IServiceWebsites
{
内部列表_网站=新列表();
内部int\u getsitescalcount;
IEnumerable Sam.Alyza.WcfInterface.IServiceWebsites.GetSites()
{
_GetSitesCallCount++;
返回(u)网站;;
}
}
唯一的问题是:如何让ViewModel调用这个模拟类而不是服务?
解决方案:Service.Use()管理连接。通过添加覆盖连接管理的功能,我能够将我自己的WCF模拟对象偷偷带到服务中。Use()。
为此,我需要一种使Service.Use()调用WCF以外的东西的方法(请参阅#DEBUG部分):

公共静态类服务
{
#如果调试
公共静态T DebugOverride=默认值(T);
#恩迪夫
公共静态通道工厂_ChannelFactory;
公共静态无效使用(UseServiceDelegate代码块)
{
#如果调试
如果(!Object.Equals(DebugOverride,默认值(T)))
{
代码块(DebugOverride);
返回;
}
#恩迪夫
如果(_channelFactory==null)
_channelFactory=新的channelFactory(“AlyzaServiceEndpoint”);
IClientChannel代理=(IClientChannel)_channelFactory.CreateChannel();
布尔成功=假;
尝试
{
代码块((T)代理);
proxy.Close();
成功=真实;
}
最后
{
如果(!成功)
{
proxy.Abort();
}
}
}
}
通过将这个测试钩子添加到服务中,我能够在测试中潜入任何实现T的对象:

MockWebsiteService mockmodel = new MockWebsiteService();
Service<WcfInterface.IServiceWebsites>.DebugOverride = mockmodel;
// run my tests here
MockWebsiteService mockmodel=新建MockWebsiteService();
Service.DebugOverride=mockmodel;
//在这里运行我的测试
对我来说,这是模拟WCF服务的一个非常好的方法


PS:我知道由于#if调试,测试不会在发行版中编译。如果您愿意的话,就把它们踢出去。

我们使用依赖注入来解决这个问题,将服务客户机(或者服务客户机的工厂)注入到ViewModel中。大概是这样的:

List<Sam.Alyza.WcfInterface.Website> rc = null;
Service<Sam.Alyza.WcfInterface.IServiceWebsites>.Use(alyzaSvc =>
{
  rc = new List<Sam.Alyza.WcfInterface.Website>(alyzaSvc.GetSites());
});
List<Sam.Alyza.WcfInterface.Website> rc = new List<Sam.Alyza.WcfInterface.Website>(_datamodel.GetSites());
interface IClientFactory
{
    TClient CreateClient<TClient>();
}

class ClientFactory : IClientFactory
{
    TClient CreateClient<TClient>() 
    {
       var channelFactory = new ChannelFactory<TClient>("AlyzaServiceEndpoint");
       var proxy = (TClient)channelFactory.CreateChannel();
       return proxy;
    }
}

public ViewModel 
{
    public ViewModel(IClientFactory clientFactory)
    {
       _clientFactory = clientFactory;
    }

    private void DoWcfStuff()
    {
        using (var proxy = _clientFactory.CreateClient<IClientChannel>())
        {
           var result = proxy.GetThings();
        }
    }
}

public ViewModelTests
{
    public void Setup()
    {
       _mockFactory = new MockClientFactory();
       _viewModel = new ViewModel(_mockFactory);
    }

    [Test]
    public void Test() 
    {
       var testResult = new Result();
       var mockClient = _mockFactory.CreateClient<IClientChannel>();

       mockClient.SetResultForGetThings(testResult);

       // put the viewmodel through its paces.
    }

    private class MockClientFactory : IClientFactory
    {
        MockClient _mockClient;

        public MockClientFactory()
        {
          _mockClient = new MockClient();
        }

        public TClient CreateClient<TClient>()
        {
           if (typeof(TClient) == typeof(IClientChannel))
           {
              return _mockClient;
           }
        }
    }

    private class MockClient : IClientChannel
    {
        void SetupGetThingsResult(Result result)
        {
           _result = result;
        }

        Result GetThings() 
        {
           return _result;
        }
    }
}
接口IClientFactory
{
TClient CreateClient();
}
类ClientFactory:IClientFactory
{
TClient CreateClient()
{
var channelFactory=新的channelFactory(“AlyzaServiceEndpoint”);
var proxy=(TClient)channelFactory.CreateChannel();
返回代理;
}
}
公共视图模型
{
公共视图模型(IClientFactory客户端工厂)
{
_clientFactory=clientFactory;
}
私人文件
{
使用(var proxy=\u clientFactory.CreateClient())
{
var result=proxy.GetThings();
}
}
}
公共视图模型测试
{
公共作废设置()
{
_mockFactory=新的MockClientFactory();
_viewModel=新的viewModel(_mockFactory);
}
[测试]
公开无效测试()
{
var testResult=新结果();
var mockClient=_mockFactory.CreateClient();
mockClient.SetResultForGetThings(testResult);
//对viewmodel进行测试。
}
私有类MockClientFactory:IClientFactory
{
MockClient\u MockClient;
公共MockClientFactory()
{
_mockClient=新的mockClient();
}
公共TClient CreateClient()
{
if(typeof(TClient)=typeof(IClientChannel))
{
返回\u mockClient;
}
}
}
私有类MockClient:IClientChannel
{