繁体   English   中英

使用FakeItEasy进行伪WCF服务调用

[英]Fake WCF-Service calls with FakeItEasy

我想测试我的类,该类称为第三方Web服务。 是否可以为此使用FakeItEasy?

我试图从Reference.cs (自动生成)伪造类,启动了UnitTest,但没有回来。

Reference.cs (自动生成)

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

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

        public AccessoryService.ResponseMessageOf_ListOf_SomeMethodInfo SomeMethod(
            AccessoryService.RequestMessageOf_SomeMethod request)
        {
            return base.Channel.SomeMethod(request);
        }
    }

Test.cs

    [Test]
    public void DoBusinessLogicTryTest()
    {
        var accessoryProxy = A.Fake<ws_AccessoryClient>();
    }

如前所述,您可能不想执行单元测试的目标,因为与使用模拟接口的单元测试相比,这会导致更多的噪音。 但是,这是进行集成测试的有效方法,这将使您能够测试WCF接线是否按预期工作。 如果您采用的是行为驱动更强的测试方式,并且希望尽可能少地进行模拟,它还允许您对应用程序进行整体测试。

我自己使用这种方法通过NSubstitute分解伪造的终结 ,这在我的博客“ 将模拟作为WCF服务托管”中有所介绍。 您需要做的主要事情是启动ServiceHost ,为其提供要使用的终结点地址,将上下文模式设置为single,并提供要用作终结点的模拟对象。

var serviceHost = new ServiceHost(mock, new[] { baseAddress });

serviceHost.Description.Behaviors
    .Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
serviceHost.Description.Behaviors
    .Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;

serviceHost.AddServiceEndpoint(typeof(TMock), new BasicHttpBinding(), endpointAddress);

我在测试中所做的一件事是随机选择托管端点的端口,并在测试过程中将地址注入到我的应用程序中。 这样,您的测试将能够在其他计算机上运行并构建服务器,而不会与使用中的其他端口冲突。

看完示例之后,您可能要考虑使用WCF ChannelFactory创建客户端,而不是使用具体的代理客户端类。 ChannelFactory使用提供的接口动态创建代理,并允许您使用服务接口将代理注入其依赖项中。 这将使单元测试更加容易,并为您提供更加分离的设计。

您不能(为什么要这么做?)。

如果要验证您的被测类是否对服务进行了调用,请将该服务调用包装在一个类中,该类的唯一工作是调用该服务,并使用接口进行定义。

interface ICallTheService
{
    void CallTheService();
}

class ServiceCaller : ICallTheService
{
    void CallTheService()
    {
        // Call the service...
    }
}

然后,您可以伪造该类并验证您的被测类是否调用CallTheService操作。

// fake the service caller and pass it into your service
var serviceCaller = A.Fake<ICallTheService>();

// Verify invocation
A.CallTo(() => serviceCaller.CallTheService()).MustHaveHappened();

我想测试类中的逻辑,具体取决于WCF-Service的响应

我认为这是您在分离关注点时出错的地方。 您的测试称为DoBusinessLogicTryTest ,但它依赖于System.ServiceModel,这是基础结构方面的问题。 没有这种依赖性,您的业务逻辑应该是可测试的。 如果测试中的类需要根据响应而有所不同,则可以执行以下操作:

interface ICallTheService
{
    ServiceResponseModel CallTheService();
}

enum ServiceResponseModel
{
    Success,
    PartialSuccess,
    FailureCondition1,
    FailureCondition2,
    // etc...
}

然后,您可以准备ICallTheService伪造品以返回每个可能的响应,并基于此测试您的类。

A.CallTo(() => serviceCaller.CallTheService()).Returns(ServiceResponseModel.Success);

例如,如果某些异常(在WCF中定义)得到正确处理

这也与业务逻辑无关。 实际的异常处理是ICallTheService实现的职责。 实际上,我将为此引入另一个类,该类的工作是将各种可能的异常从System.ServiceModel转换为您的响应模型。 例如

class WCFErrorResponseTranslator
{
    ServiceResponseModel TranslateWCFException (Exception ex)
    {
        if (ex.GetType() == typeOf(TimeoutException)) { return ServiceResponseModel.TimeOut; }
        /// etc
    }
}

然后可以单独测试此行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM