2013-01-11 164 views
0

我开发使用CookComputing XML-RPC.net应用单元测试/嘲讽XML-RPC.net电话

我的问题是如何单元调用外部RPC方法的测试方法。

如果我们把网站上的例子:

//This is the XML rpc Proxy interface 
[XmlRpcUrl("http://www.cookcomputing.com/xmlrpcsamples/RPC2.ashx")] 
public interface IStateName : IXmlRpcProxy 
{ 
    [XmlRpcMethod("examples.getStateName")] 
    string GetStateName(int stateNumber); 
} 


public class MyStateNameService 
{ 
    public string GetStateName(int stateNumber) 
{ 
     IStateName proxy = XmlRpcProxyGen.Create<IStateName>(); 
     return proxy.GetStateName(stateNumber); 
    } 
} 

我们怎样才能有效地测试IStateName的结果,而无需实际击中 http://www.cookcomputing.com/xmlrpcsamples/RPC2.ashx

我认为一个良好的开端将是对MyStateNameService回吐构造一个IStateName,并在IStateName上传递一个虚假(或模拟?)实例...

我很想测试它的实际内容 - 例如伪装响应SE从端点,并返回,不知怎的,不仅验证GetStateName调用服务...

编辑

我并不想测试服务为这样的内容,而且什么我的类与它做。

因此,例如,说的回应是:

<?xml version="1.0"?> 
<methodResponse> 
    <params> 
    <param> 
     <value><string>My State Name</string></value> 
    </param> 
    </params> 
</methodResponse> 

我会想“假”该响应一些如何测试MyStateNameService.GetStateName实际返回的“我的国家名称”

+0

为什么你要测试的内容?当然,一旦它被命中'IStateName'代理它不再是你的应用程序的关注。不要测试外部代码,这取决于编写库的人! –

+0

对不起......我将编辑问题以使其更清晰。请参阅编辑问题 – Alex

+0

我仍然不确定这一点。纠正我,如果我错了,但你不直接处理XML,你调用代理上的一个方法,它会创建一个请求,并将它发送到为RPC提供服务的任何地方。响应返回到代理,然后解析输出并提供给您?在这种情况下,你无法控制XML解析,图书馆的代理类可以完成它,那么为什么要测试它呢? –

回答

0

你的问题在于这里应用的单例模式。

XmlRpcProxyGen.Create<IStateName>(); 

所以你的想法与使用依赖注入(通过构造函数)是一个好的开始。 (您是否使用IoC容器?)

接下来是为IStateName服务创建模拟/伪造/存根。 这可以通过许多方式来实现。

使用动态嘲弄的系统可以为您节省一些工作的其他自动/动态模拟框架,但你需要了解他们的用法。

使用NUnit的,NSubstitute和修改MyStateNameService经典AAA测试的例子:

class MyStateNameService 
{ 
    private readonly IStateName _remoteService; 
    public MyStateNameService(IStateName remoteService) 
    { 
    // We use ctor injection to denote the mandatory dependency on a IStateName service 
    _remoteService = remoteService; 
    } 

    public string GetStateName(int stateNumber) 
    { 
    if(stateNumber < 0) throw new ArgumentException("stateNumber"); 
    // Do not use singletons, prefer injection of dependencies (may be IoC Container) 
    //IStateName proxy = XmlRpcProxyGen.Create<IStateName>(); 
    return _remoteService.GetStateName(stateNumber); 
    } 
} 

[TestFixture] class MyStateNameServiceTests 
{ 
    [Test] 
    public void SomeTesting() 
    { 
    // Arrange 
    var mockService = Substitute.For<IStateName>(); 
    mockService.GetStateName(0).Returns("state1"); 
    mockService.GetStateName(1).Returns("state2"); 

    var testSubject = new MyStateNameService(mockService); 


    // Act 
    var result = testSubject.GetStateName(0); 

    // Assert 
    Assert.AreEqual("state1", result); 

    // Act 
    result = testSubject.GetStateName(1); 

    // Assert 
    Assert.AreEqual("state2", result); 

    // Act/Assert 
    Assert.Throws<ArgumentException>(() => testSubject.GetStateName(-1)); 
    mockService.DidNotReceive().GetStateName(-1); 

    /* 
     MyStateNameService does not do much things to test, so this is rather trivial. 
     Also different use cases of the testSubject should be their own tests ;) 
    */ 


    } 

} 
+0

是的,我知道*我需要做什么,只是在这里寻找更深入的答案....我可能会使用moq – Alex

+0

我可以给你代码测试与NSubstitute MyStateNameService,不知道多少关于moq虽然... – sanosdole

+0

这很好,我主要概念,使用任何库。我不是'给我一个codez'类型的用户;-) – Alex