Jos*_*eph 39
我通常做的是围绕我的Web服务构建一个包装器或适配器,然后嘲笑它.
例如:
public class ServiceAdapter: IServiceAdapter
{
public void CallSomeWebMethod()
{
var someService = new MyWebService();
someService.SomeWebMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我只是存根服务适配器.
[Test]
public void SomeMethod_Scenario_ExpectedResult()
{
var adapterMock = new Mock<IServiceAdapter>();
//do your test
}
Run Code Online (Sandbox Code Playgroud)
joh*_*y g 34
最近一直在写关于单元测试和嘲笑的几个回复.我在别处写过,问问自己究竟在测试什么是很重要的.关于你的具体情况,我希望答案是"我正在测试我的WebService正在暴露的业务逻辑",而不是 "我正在测试我的WebService" - 这是有区别的.
如果您担心的是服务器端问题
您通常不需要测试WebServices.MS已经做到了.数百万人已经做到了.测试传输层,协议,WebServices的定义是浪费时间.
您需要定位业务逻辑.执行此操作的最佳方法是将业务逻辑与WebService 分开.考虑以下
public class MyWebSevice : System.Web.Services.WebService
{
private AuthenticationService _auth = new AuthenticationService ();
private int _count = 0;
[WebMethod]
public string DoSomething ()
{
// embedded business logic, bad bad bad
if (_auth.Authenticate ())
{
_count++;
}
return count.ToString ();
}
}
Run Code Online (Sandbox Code Playgroud)
没有直接调用WebService就无法测试该逻辑.你真正想要的是什么
public class MyService
{
// keeners will realise this too should be injected
// as a dependency, but just cut and pasted to demonstrate
// isolation
private AuthenticationService _auth = new AuthenticationService ();
private int _count = 0;
public string DoSomething ()
{
if (_auth.Authenticate ())
{
_count++;
}
return count.ToString ();
}
}
Run Code Online (Sandbox Code Playgroud)
在prod
// this web service is now a consumer of a business class,
// no embedded logic, so does not require direct testing
public class MyWebSevice : System.Web.Services.WebService
{
private readonly MyService _service = new MyService ();
[WebMethod]
public string DoSomething ()
{
_service.DoSomething ();
}
}
Run Code Online (Sandbox Code Playgroud)
在测试中
// test business logic without web service! yay!
[Test]
public void Test_DoSomething ()
{
MyService service = new MyService ();
string actual = service.DoSomething ();
// verify results
}
Run Code Online (Sandbox Code Playgroud)
管理依赖项[如AuthenticationService成员]是一个单独的问题.但是,使WebMethods 简单直接到正确的底层业务类并完全从中删除逻辑,允许您定位"真实"用户代码而不是典型WebService实现的管道.
如果您的顾虑是客户方面的
您有一个调用 Web服务的业务组件,我同意您不希望为单元测试创建客户端.
public partial class MyWebService :
System.Web.Services.Protocols.SoapHttpClientProtocol
{
...
public string DoSomething () { ... }
}
public class MyClient
{
public void CallService ()
{
MyWebService client = new MyWebService ();
client.DoSomething ();
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,您有依赖性问题,即无法在不实例化和托管WebService的情况下测试MyClient.CallService.如果您不拥有或托管所述远程服务,尤其令人不安.在这种情况下,是的,你应该写一个接口 - 再次分离和隔离业务逻辑.
public interface IMyWebService
{
string DoSomething ();
}
public class MyWebServiceWrapper : IMyWebService
{
public string DoSomething ()
{
MyWebService client = new MyWebService ();
client.DoSomething ();
}
}
public class MyClient
{
private readonly IMyWebService _client = null;
public MyClient () : this (new MyWebServiceWrapper ()) { }
public MyClient (IMyWebService client)
{
_client = client;
}
public void CallService ()
{
_client.DoSomething ();
}
}
Run Code Online (Sandbox Code Playgroud)
在测试中
[Test]
public void Test_CallService ()
{
IMyWebService mockService = null;
// instantiate mock with expectations
MyClient client = new MyClient (mockService);
client.CallService ();
// verify results
}
Run Code Online (Sandbox Code Playgroud)
通常,如果类的依赖项是进程内服务,那么应用依赖注入[DI]或控制反转[IoC]等模式的决定取决于您 - 并且您希望隔离和单元测试这些服务将通知您设计.但是,如果类的依赖项跨越进程边界,例如数据库或WebService,我强烈建议像上面那样应用这些模式.
真的,这只是简单的旧界面开发.你可能已经看到它是如何得到回报的.
:)