我正在开发一个使用CookComputing 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上传入一个伪造的(或模拟的?)实例...
我有兴趣测试它的实际内容 - 例如,从终端获取响应,并以某种方式返回,而不仅仅是验证GetStateName
是否调用了服务......
修改
我不是试图测试服务的内容,而是我的类用它来测试。
因此,举例来说,回答是:
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>My State Name</string></value>
</param>
</params>
</methodResponse>
我想'伪造'那个回复如何测试MyStateNameService.GetStateName
实际返回的'我的州名'
答案 0 :(得分:0)
您的问题在于此处应用的Singleton模式。
XmlRpcProxyGen.Create<IStateName>();
因此,使用依赖注入(通过构造函数)的想法是一个良好的开端。 (您使用的是IoC容器吗?)
接下来是为IStateName
服务创建一个Mock / Fake / Stub。
这可以通过多种方式实现。
使用动态模拟系统可以为您节省一些工作,但您需要了解它们的用法。
使用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 ;)
*/
}
}