【问题标题】:Unit Test - How to MOQ WCF Client using MOQ单元测试 - 如何使用 MOQ 对 WCF 客户端进行 MOQ
【发布时间】:2016-10-18 14:49:50
【问题描述】:

我一直在查看many other questions on SO,很多类似的,但似乎没有一个与服务参考的风格相匹配,因此我问。他们中的大多数人都在谈论使用ChannelFactory,但这个使用ClientBase。我正在了解有关单元测试和起订量的更多信息。我想测试我们的存储库类,它会调用 WCF 服务。

我尝试了很多方法来模拟,包括在 repo 上创建一个构造函数,采用 FISP 接口。

我怎样才能使它在 repo 中可用并且也可单元测试,使用 moq 模拟 WCF 操作?

repository(还)没有传入接口,如下。它正在使用代理客户端类。

public class FisPRepository : IFisPRepository
{
    private readonly FISPClient _fisPClient;

    public FisPRepository()
    {
        _fisPClient = new FISPClient
        {
            ClientCredentials =
            {

                UserName = {UserName = "xyz", Password = "cba"}
            }
        };

    public person GetPersonFromId(string id)
    {
        return _fisPClient.getPerson(new personRequest()
        {
            reference = new referenceFilter { type = "FWI", value = id },
        });
    }
}

生成的参考

这是生成的参考代码 -

界面:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.aUrl.com/fwi", ConfigurationName="FISP.FISP")]
public interface FISP {
    [System.ServiceModel.OperationContractAttribute(Action="http://www.aUrl.com/fwi/FISP/getPersonRequest", ReplyAction="http://www.aUrl.com/fwi/FISP/getPersonResponse")]
    [System.ServiceModel.FaultContractAttribute(typeof(FhSoap.FISP.FWiException), Action="http://www.aUrl.com/fwi/FISP/getPerson/Fault/FWiException", Name="FWiException")]
    [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(episodeTask))]
    [return: System.ServiceModel.MessageParameterAttribute(Name="person")]
    FhSoap.FISP.getPersonResponse getPerson(FhSoap.FISP.getPersonRequest request);  
}

客户:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface FISPChannel : FhSoap.FISP.FISP, System.ServiceModel.IClientChannel {
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class FISPClient : System.ServiceModel.ClientBase<FhSoap.FISP.FISP>, FhSoap.FISP.FISP {
    public FISPClient() {
    }

    public FISPClient(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
    FhSoap.FISP.getPersonResponse FhSoap.FISP.FISP.getPerson(FhSoap.FISP.getPersonRequest request) {
        return base.Channel.getPerson(request);
    }

    public FhSoap.FISP.person getPerson(FhSoap.FISP.personRequest request) {
        FhSoap.FISP.getPersonRequest inValue = new FhSoap.FISP.getPersonRequest();
        inValue.request = request;
        FhSoap.FISP.getPersonResponse retVal = ((FhSoap.FISP.FISP)(this)).getPerson(inValue);
        return retVal.person;
    }
}

更新

按照下面 cmets 中的建议,我尝试使用接口构建客户端,这是什么意思?因为这不会创建一个客户端,它会创建一个通道。

    public FisPRepository()
    {
        var factory = new ChannelFactory<FISPChannel>("BasicHttpBinding_SomthingService");

        var credentialBehaviour = factory.Endpoint.Behaviors.Find<ClientCredentials>();
        credentialBehaviour.UserName.UserName = "xyz";
        credentialBehaviour.UserName.Password = "cba";

        _fisPClient = factory.CreateChannel();
    }

_fisPClient = factory.CreateChannel(); 无效,因为它创建的是 FISPChannel,而不是客户端。我错过了什么?

【问题讨论】:

  • 您的存储库正在使用您的具体客户端,您需要将客户端注入到接口中的类中。
  • 但这不是一个接口,所以我不能模拟它。
  • @DavidC,客户端实现了接口,因此您可以将具体类换成抽象。
  • @Kritner,FISP 频道?与 FISP 接口相反?

标签: c# wcf unit-testing moq


【解决方案1】:

您的存储库正在使用您的具体客户端,您需要将客户端注入到接口上的类中

回复:

@Kritner,FISP 频道?与 FISP 接口相反?

嗯,正常的约定是接口是“我”,类似于IFISP,但不管怎样,IFISP 接口是我过去使用的接口(而不是IFISPChannel。虽然目前,如果您尝试使用FISP,则该接口将无法访问您当前在新建客户端时在类中设置的ClientCredentials

理想情况下,您不会在每个存储库上设置凭据,而是在某种配置中。完成此操作后,您可以重构为以下内容:

public class FisPRepository : IFisPRepository
{
    private readonly FISP _fisp;

    public FisPRepository(FISP fisp)
    {
        _fisp = fisp;
    }

    public person GetPersonFromId(string id)
    {
        return _fisP.getPerson(new personRequest()
        {
            reference = new referenceFilter { type = "FWI", value = id },
        });
    }
}

当然,在构建存储库时,您需要传入客户端的具体化 - 但对于单元测试,您将能够模拟 FISP

您可以通过多种方式获得客户端的具体化。

  • 使用 IOC 容器,例如 Ninject、Unity、AutoFac 等
  • 直接新建混凝土
  • 使用服务位置

由于语法因您的 IOC 或服务位置而异,因此您现在可以直接获取存储库:

FisPRepository myRepo = new FisPRepository(new FISPClient());

将您的具体化和编码注入抽象是 design pattern,称为依赖注入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 2011-12-24
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    相关资源
    最近更新 更多