How would you Unitest this code?
Need some help in Unitestsing. (Assume I don't have a TypeMock)
Would you change the code in order to inject mocks to substitute EndpointAddress, DiscoveryEndpoint, DiscoveryClient ?
What kind of tests would you write? I can th开发者_运维技巧ink of
GetService_ServiceExist_ResultShouldBeAnInstance
GetService_ServiceIsNotExist_ResultShouldNull
static public T GetService<T>(Binding binding, string address)
{
Contract.Requires(binding != null);
Contract.Requires(!string.IsNullOrWhiteSpace(address));
var endpointAddress= new EndpointAddress(address);
var discoveryEndpoint = new DiscoveryEndpoint(binding, endpointAddress);
var discoveryClient = new DiscoveryClient(discoveryEndpoint);
try
{
// Find ICalculatorService endpoints
FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(T)));
Contract.Assume(findResponse != null);
Contract.Assume(findResponse.Endpoints != null);
// Check to see if endpoints were found, if so then invoke the service.););
if (findResponse.Endpoints.Count > 0)
{
Contract.Assume(findResponse.Endpoints[0] != null);
return ChannelFactory<T>.CreateChannel(new BasicHttpBinding(),
findResponse.Endpoints[0].Address);
}
}
catch (TargetInvocationException ex)
{
Console.WriteLine("This client was unable to connect to and query the proxy. Ensure that the proxy is up and running: " + ex);
}
return default(T);
}
Appreciate any of your help. Thanks!
Ariel
You have a dependency on EndpointAddress, DiscoveryEndpoint and DiscoveryClient in your method.
First off is I'd put this code into something resembling a factory. I'd also put the above dependencies into factories if necessary and then inject those factories into the class using IOC.
Then that lets me put fake objects (or mocks) into the system for unit testing and I don't have to rely on a concrete discoveryclient (for example). But if that isn't an issue, I'd still factory it.
You're also looking at finding an endpoint and creating a channel on that or throwing an exception. Well if you stick with the above then do you need to be returning default(T).
Choice here is to either keep the code in there and then throw the exception rather than return null, return null and test for it, make this method only do one thing which is to attempt to create a channel based on a configured DiscoveryClient.
If I was doing it, I'd remove all those dependencies, make it a factory (and the others from factories as necessary) then pass in a configured DiscoveryClient and either return null or return a NullChannel instance.
Then I can do an assert on the instance returned in my test and the creation method only has one responsibility.
HTH
精彩评论