I'm learning about unit testing in C#. Languages_Service
and PlaceOfWork_Service
are classes for SOAP services which Microsoft Navision generated for me. There are several methods that are very similar (see the two examples below).
[TestMethod]
public void Languages()
{
string serviceUrl = Helper.GetBaseUrl() + "Languages";
Languages_Service service = new Languages_Service();
service.Credentials = Helper.GetCredentials();
service.Url = serviceUrl;
Languages_Filter[] filter = { new Languages_Filter() };
service.ReadMultiple(filter, null, 0);
}
[TestMethod]
public void PlaceOfWork()
{
string serviceUrl = Helper.GetBaseUrl() + "PlaceOfWork";
PlaceOfWork_Service service = new PlaceOfWork_Service();
service.Credentials = Helper.GetCredentials();
service.Url = serviceUrl;
PlaceOfWork_Filter[] filter = { new PlaceOfWork_Filter() };
service.ReadMultiple(filter, null, 0);
}
Method ReadMultiple of Language_Service looks like so:
public Languages[] ReadMultiple([System.Xml.Serialization.XmlElementAttribute("filter")] Languages_Filter[] filter, string bookmarkKey, int setSize)
{
object[] results = this.Invoke("ReadMultiple", new object[] {
filter,
bookmarkKey,
setSize});
return ((Languages[])(results[0]));}
Method ReadMultiple of PlaceOfWork_Service looks like so:
public PlaceOfWork[] ReadMultiple([System.Xml.Serialization.XmlElementAttribute("filter")] PlaceOfWork_Filter[] filter, string bookmarkKey, int setSize) {
object[] results = this.Invoke("ReadMultiple", new object[] {
filter,
bookmarkKey,
setSize});
return ((PlaceOfWork[])(results[0]));
}
How could one write something like the (pseudo) code below?
[TestMethod]
public void GunAndSmokeTestAllSerivces()
{
Dictionary<String, List<Type>> servicesToTest = new Dictionary<String, List<Type>>();
servicesToTest.Add("Languages", new List<Type>(new Type[] { typeof(Languages_Service), typeof(Languages_Filter) }));
servicesToTest.Add("PlaceOfWork", new List<Type>(new Type[] { typeof(PlaceOfWork_Service), typeof(PlaceOfWork_Filter) }));
foreach (KeyValuePair<String, List<Type>> entry in servicesToTest)
{
var t1 = entry.Value.ToArray()[0];
var t2 = entry.Value.ToArray()[1];
SoapHttpClientProtocol service = (SoapHttpClientProtocol)Activator.CreateInstance(t1);
service.Credentials = Helper.GetCredentials();
service.Url = Helper.GetBaseUrl() + entry.Key;
object[] filter = { (object)Activator.CreateInstance(t2) };
service.ReadMultiple(filter, null, 0);
}
}
Languages_Service
and PlaceOfWork_Service
are subclasses of System.Web.Services.Protocols.SoapHttpClientProtocol
.
Best Answer
You probably don't want to do exactly what you describe because then you'd have a single test method covering multiple test cases. This isn't great because it means your tests lose granularity, so:-
A simpler and probably more applicable solution is just to do what you normally do when there's repeated code like this- pull it out into a parameterized method:
That's the basic version, just to give you a rough idea. As the comments said this seems incomplete without assertions, and there may be better ways to split this into multiple methods. You should also come up with better names based on your understanding of what exactly these tests are for.
A few issues to take note of:
ReadMultiple
isn't a method onSoapHttpClientProtocol
. You'll need a superclass or interface with this method, and have that as a constraint on yourTService
generic parameter.TFilter
may need some similar constraintReadMultiple
line, or they could provide anAction<TService,TFilter[]>
or similarnew()
constraint, you'll instead want to remove it and have aTService
parameter on the method, and leave the individual test in charge of doing the construction.