I'm developing an application that uses CookComputing XML-RPC.net
My question is how to unit test methods that call an external rpc method.
If we take the example on the site:
//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);
}
}
How can we effectively test the result of IStateName without actually hitting http://www.cookcomputing.com/xmlrpcsamples/RPC2.ashx
I suppose a good start would be a constructor on MyStateNameService
taking an IStateName, and passing in a fake (or mocked?) instance on IStateName...
I'm interested in testing it for actual content - for example faking up the response from the endpoint, and returning that somehow, not just verifying that GetStateName
calls the service...
Edit
I'm not trying to test the content of the service as such, moreover what my classes do with it.
So, for example, say the response is:
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>My State Name</string></value>
</param>
</params>
</methodResponse>
I'd want to 'fake' that response some how to test that MyStateNameService.GetStateName
actually returned 'My State Name'
Your problem lies in the Singleton Pattern applied here.
XmlRpcProxyGen.Create<IStateName>();
So your idea with using Dependency Injection (By Constructor) is a good start. (Do you use an IoC container?)
Next is to create a Mock/Fake/Stub for the IStateName
service. This can be achieved by many ways.
Using a dynamic mocking system may save you some work, but you need to learn their usage.
Classic AAA testing example for using NUnit, NSubstitute and a modified MyStateNameService
:
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 ;)
*/
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.