我们即将开始构建面向服务的框架 (SOA),它肯定会涉及大量细粒度的 Web 服务(WCF 中的 REST)。我们在对客户端和服务器端代码库进行单元测试方面非常严格,但是我们在单元测试 Web 服务方面没有太多经验。我们真的在寻找关于应该在哪里编写测试的指导以及在对我们的服务进行单元测试时使用什么方法的建议。
我们是否应该编写发出 http 请求的测试并断言响应是它们应该的样子?我们是否应该只专注于测试服务方法本身的内部逻辑,而不必担心测试实际请求?还是我们应该两者都做?对于我们应该测试的内容,还有其他建议吗?
我们真的在寻找一些解释和指导,并且非常感谢我们能得到的任何建议。
最佳答案
我发现测试 Web 服务,特别是 WCF 客户端和服务器,在以下场景中在常规单元测试之上非常有用:
大多数时候,我尝试使用带有基本 http 的非常基本的设置并将所有内容连接到代码中。除非我是集成或验收测试,否则我不会针对服务器测试客户端,而是模拟其中一个,以便我可以单独测试另一个。以下是我如何测试 WCF 客户端和服务的示例:
public static ServiceHost CreateServiceHost<TServiceToHost>(TServiceToHost serviceToHost, Uri baseAddress, string endpointAddress)
{
var serviceHost = new ServiceHost(serviceToHost, new[] { baseAddress });
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
serviceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
serviceHost.AddServiceEndpoint(typeof(TServiceToHost), new BasicHttpBinding(), endpointAddress);
return serviceHost;
}
//Testing Service
[TestFixture]
class TestService
{
private ServiceHost myServiceUnderTestHost;
private ChannelFactory<IMyServiceUnderTest> myServiceUnderTestProxyFactory;
[SetUp]
public void SetUp()
{
IMyServiceUnderTest myServiceUnderTest = new MyServiceUnderTest();
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
myServiceUnderTestProxyFactory = new ChannelFactory<IMyServiceUnderTest>(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345/ServiceEndPoint"));
}
[TearDown]
public void TearDown()
{
myServiceUnderTestProxyFactory.Close();
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
IMyServiceUnderTest serviceProxy = myServiceUnderTestProxyFactory.CreateChannel();
serviceProxy.SomeMethodCall();
}
}
//Testing Client
[TestFixture]
class TestService
{
private ServiceHost myMockedServiceUnderTestHost;
private IMyServiceUnderTest myMockedServiceUnderTest;
[SetUp]
public void SetUp()
{
myMockedServiceUnderTest = Substitute.For<IMyServiceUnderTest>(); //Using nsubstitute
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myMockedServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
}
[TearDown]
public void TearDown()
{
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
//Create client and invoke methods that will call service
//Will need some way of configuring the binding
var client = new myClientUnderTest();
client.DoWork();
//Assert that method was called on the server
myMockedServiceUnderTest.Recieved().SomeMethodCall();
}
}
注意
我忘了提到,如果你想使用任何使用城堡动态代理的东西来模拟 WCF 服务,那么你需要阻止
ServiceContractAttribute
从被复制到模拟。我有一个 blog post在这一点上,但基本上您将属性注册为一个以防止在创建模拟之前复制。Castle.DynamicProxy.Generators.AttributesToAvoidReplicating
.Add<ServiceContractAttribute>();
关于wcf - 单元测试 Web 服务的推荐模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9587393/