如何模拟Web服务

zac*_*ary 25 .net c# web-services moq mocking

我是否必须重写我的代码才能在界面中执行此操作?或者有更简单的方法吗?我正在使用Moq

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,我强烈建议像上面那样应用这些模式.

真的,这只是简单的旧界面开发.你可能已经看到它是如何得到回报的.

:)


Jon*_*eet 10

很久以前我在博客上写过这篇文章.基本上使用部分类和一些努力(自动或手动,取决于您将更改Web服务的频率),您可以使Web服务代理类实现一个接口.然后你可以正常模拟它.