使用 FakeItEasy 伪造 WCF 服务调用
Fake WCF-Service calls with FakeItEasy
我想测试我的 Class,它调用第三方 Web 服务。是否可以为此使用 FakeItEasy?
Wenn 我尝试从 Reference.cs
(自动生成)中伪造 Class,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>();
}
你不能(你为什么要这么做?)。
如果你想验证你的 class 被测是否调用了服务,然后将服务调用包装在一个 class 中,它的唯一工作就是调用服务,并定义它有一个界面。
interface ICallTheService
{
void CallTheService();
}
class ServiceCaller : ICallTheService
{
void CallTheService()
{
// Call the service...
}
}
然后你可以伪造这个 class 并验证你的 class 在测试中调用了 CallTheService 操作。
// fake the service caller and pass it into your service
var serviceCaller = A.Fake<ICallTheService>();
// Verify invocation
A.CallTo(() => serviceCaller.CallTheService()).MustHaveHappened();
I want to test the logic in my class, depends on Response from
WCF-Service
这就是我认为您在关注点分离方面出错的地方。您的测试名为 DoBusinessLogicTryTest,但它依赖于 System.ServiceModel,这是一个基础设施问题。在没有这种依赖性的情况下,您的业务逻辑应该是可测试的。如果您的 class 被测需要根据响应做出不同的行为,您可以这样做:
interface ICallTheService
{
ServiceResponseModel CallTheService();
}
enum ServiceResponseModel
{
Success,
PartialSuccess,
FailureCondition1,
FailureCondition2,
// etc...
}
然后你可以将 ICallTheService 伪装成 return 每个可能的响应并基于此测试你的 class。
A.CallTo(() => serviceCaller.CallTheService()).Returns(ServiceResponseModel.Success);
For Example if some Exceptions (defined in WCF) are handled correct
这也与业务逻辑无关。异常的实际处理是 ICallTheService 实现的责任。事实上,我会为此引入另一个 class,其工作是将 various possible exceptions 从 System.ServiceModel 转换为您的响应模型。例如
class WCFErrorResponseTranslator
{
ServiceResponseModel TranslateWCFException (Exception ex)
{
if (ex.GetType() == typeOf(TimeoutException)) { return ServiceResponseModel.TimeOut; }
/// etc
}
}
然后可以单独测试此行为。
如前所述,您可能不想按照单元测试的目的进行操作,因为这会导致比使用模拟接口的单元测试所需的噪音更多。然而,这是一种有效的集成测试方法,这将允许您测试您的 WCF 接线是否按预期工作。如果您采用更多行为驱动的测试方式,并且希望尽可能少地进行模拟,它还允许您对应用程序进行整体测试。
我自己使用这种方法来使用 NSubstitute which is covered in my blog Hosting a Mock as a WCF service. The main things you need to do is spin up a ServiceHost 启动假端点,给它你想要使用的端点地址,将上下文模式设置为单一并提供你想要用作端点的模拟。
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 创建您的客户端,而不是使用具体的代理客户端 class。 ChannelFactory 使用您提供的接口动态创建一个代理,并允许您使用服务接口将代理注入到它的依赖项中。这将使单元测试更容易,并为您提供更解耦的设计。
我想测试我的 Class,它调用第三方 Web 服务。是否可以为此使用 FakeItEasy?
Wenn 我尝试从 Reference.cs
(自动生成)中伪造 Class,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>();
}
你不能(你为什么要这么做?)。
如果你想验证你的 class 被测是否调用了服务,然后将服务调用包装在一个 class 中,它的唯一工作就是调用服务,并定义它有一个界面。
interface ICallTheService
{
void CallTheService();
}
class ServiceCaller : ICallTheService
{
void CallTheService()
{
// Call the service...
}
}
然后你可以伪造这个 class 并验证你的 class 在测试中调用了 CallTheService 操作。
// fake the service caller and pass it into your service
var serviceCaller = A.Fake<ICallTheService>();
// Verify invocation
A.CallTo(() => serviceCaller.CallTheService()).MustHaveHappened();
I want to test the logic in my class, depends on Response from WCF-Service
这就是我认为您在关注点分离方面出错的地方。您的测试名为 DoBusinessLogicTryTest,但它依赖于 System.ServiceModel,这是一个基础设施问题。在没有这种依赖性的情况下,您的业务逻辑应该是可测试的。如果您的 class 被测需要根据响应做出不同的行为,您可以这样做:
interface ICallTheService
{
ServiceResponseModel CallTheService();
}
enum ServiceResponseModel
{
Success,
PartialSuccess,
FailureCondition1,
FailureCondition2,
// etc...
}
然后你可以将 ICallTheService 伪装成 return 每个可能的响应并基于此测试你的 class。
A.CallTo(() => serviceCaller.CallTheService()).Returns(ServiceResponseModel.Success);
For Example if some Exceptions (defined in WCF) are handled correct
这也与业务逻辑无关。异常的实际处理是 ICallTheService 实现的责任。事实上,我会为此引入另一个 class,其工作是将 various possible exceptions 从 System.ServiceModel 转换为您的响应模型。例如
class WCFErrorResponseTranslator
{
ServiceResponseModel TranslateWCFException (Exception ex)
{
if (ex.GetType() == typeOf(TimeoutException)) { return ServiceResponseModel.TimeOut; }
/// etc
}
}
然后可以单独测试此行为。
如前所述,您可能不想按照单元测试的目的进行操作,因为这会导致比使用模拟接口的单元测试所需的噪音更多。然而,这是一种有效的集成测试方法,这将允许您测试您的 WCF 接线是否按预期工作。如果您采用更多行为驱动的测试方式,并且希望尽可能少地进行模拟,它还允许您对应用程序进行整体测试。
我自己使用这种方法来使用 NSubstitute which is covered in my blog Hosting a Mock as a WCF service. The main things you need to do is spin up a ServiceHost 启动假端点,给它你想要使用的端点地址,将上下文模式设置为单一并提供你想要用作端点的模拟。
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 创建您的客户端,而不是使用具体的代理客户端 class。 ChannelFactory 使用您提供的接口动态创建一个代理,并允许您使用服务接口将代理注入到它的依赖项中。这将使单元测试更容易,并为您提供更解耦的设计。