Monthly Archives: October 2015

Testing by Interface

Given a standard interface, how to retrieve all implementing classes and run the interface methods.

Unit testing through test driven development is definitely a good idea; but what if you have a number of methods that all effectively do the same thing; that is, each method might do something completely different, but as far as it’s interface goes, it’s identical.

Imagine, for example, that you have a method that calls to the DB, and accepts a number of parameters in, and returns a given parameter. In a unit testing scenario, the DB would be mocked out, and the method called directly from the unit test. Okay, so in this case, you may want some test coverage that your methods call a mocked out DB function, don’t crash, accept a given object, accept null, etc…

Facing the same problem, it occurred to me that it should be possible to write a single test method that would test every existing and future implementation of this, without having to laboriously re-create the test each time I create a method; what’s more, as soon as I create my method name that implements the interface, I get a failing test.

Below is an interface and a test class; it is entirely for the purpose of illustration:

    public class ModelClass
    {
        public string TestProperty { get; set; }
    }


    public interface ITest
    {
        void method1();

        void method2(ModelClass model, int i);
    }

    public class Class1 : ITest
    {
        public void method1()
        {
        }

        public void method2(ModelClass model, int i)
        {
            if (model == null) throw new Exception("test");
            //if (string.IsNullOrWhiteSpace(model.TestProperty)) throw new Exception("Doh");
        }
    }

    public class Class2 : ITest
    {
        public void method1()
        {
            //throw new NotImplementedException();
        }

        public void method2(ModelClass model, int i )
        {
            
        }
    }

    public class Class3
    {
        public void  NonInterfaceMethod(ModelClass model)
        {
            throw new Exception("Doh!");
        }
    }

    public class Class4 : ITest
    {
        public void method1()
        {
            //throw new NotImplementedException();
        }

        public void method2(ModelClass model, int i)
        {
            
        }

        public void test()
        {

        }
    }

 

As you can see, there are a number of interface, and non-interface methods here. There’s nothing particularly interesting, although have a look at Class1.method2(), which should do nothing, but switching the statements should cause a runtime error, if my method works. Also, have a look at Class3.NonInterfaceMethod() – this should never be called, but will throw an exception if it is.

The following is the test code:

        [TestMethod]
        public void TestITestImplementations()
        {
            // Use reflection to get the available methods for the interface
            Type desiredType = typeof(ITest);
            Assembly assembly = desiredType.Assembly;
            var interfaceMethods = desiredType.GetMethods();
            
            // Iterate through each implementation of the interface
            foreach (Type type in assembly.GetTypes())
            {
                if (desiredType.IsAssignableFrom(type) && !type.IsInterface)
                {
                    // Where an implementation is found, instantiate it 
                    // and build a list of available methods to call
                    var classInstance = Activator.CreateInstance(type, null);
                    var methods = type.GetMethods()
                        .Where(m => interfaceMethods.Any(i => i.Name == m.Name)
                            && m.IsPublic
                            && !m.DeclaringType.Equals(typeof(object)));
                    foreach(var method in methods)
                    {
                        // Establish the available parameters and pass them to the call
                        var p = method.GetParameters();
                        object[] p2 = p.Select(a => Activator.CreateInstance(a.ParameterType)).ToArray();

                        try
                        {
                            // Call the method and, where a value should be returned, ensure one is
                            object result = method.Invoke(classInstance, p2);
                            Assert.IsFalse(method.ReturnType != typeof(void) && result == null);
                        }
                        catch(Exception ex)
                        {
                            // Where an error is thrown, print a sensible error
                            Assert.Fail("Call failed: {0}.{1}\nException: {2}", 
                                type.Name, method.Name, ex);
                        }
                    }
                }
            }            
        }

The code above is relatively straight-forward and, if I’m being honest, is only a cursory test. It tests that the methods can be called without throwing an error and, where a value should be returned, checks that it’s not null.

Obviously, it might be perfectly valid that it is null, or an exception might be the desired behaviour. This code is basically just a starting point, but it does provide some very basic test coverage where otherwise, there might be none.

It is also true to say that the code doesn’t deal with overloads, which are not necessary in my particular circumstance.

WCF Debugging

WCF is a good product in so many respects; but error reporting isn’t one of them. Whilst trying to get a WCF service to work, I encountered this error:

Exception thrown: ‘System.ServiceModel.CommunicationException’ in mscorlib.dll

Additional information: An error occurred while receiving the HTTP response to http://localhost:17065/Service1.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

WCFError

Diagnosis

The following will produce a surprisingly useful diagnosis file.

To add diagnostics, edit the web.config of the service and add:

<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>

      <source name="TraceSource" switchValue="Warning, ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>      

    </sources>
    <sharedListeners>
      <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\trc.svclog"/>
    </sharedListeners>
  </system.diagnostics>

And then:

  <system.serviceModel>
    <diagnostics wmiProviderEnabled="true">
      
    </diagnostics>

Now replicate the error and have a look in the directory you pointed the initializeData to (in my case c:\trc.svclog). Providing you’ve used the correct extension, double clicking the file should give you something like this:

WCFTrace

Sending Binary Files Over WCF

This is an interesting one – it is possible to load a binary file (such as an exe) in a .NET service and return it to the client via WCF. It’s actually not that complex either; in this example, I’ve created a basic service and console application.

Code

The code for the service is really straight forward:

    public class Service1 : IService1
    {
        public Stream GetData(int value)
        {
            FileStream stream = File.OpenRead(@"c:\tmp\MyFile");
            return stream;
        }
    }

And here is the Interface:

    [ServiceContract]
    public interface IService1
    {

        [OperationContract]
        Stream GetData(int value);
    }

The important part about the above code is that the method must return a Stream, and can only accept a single parameter (you can send large data by reversing this).

The client code is a little more involved. The Main() function of the console app is here:

        static void Main(string[] args)
        {
            Task rd = ReceiveData();
            rd.Wait();

And ReceiveData() looks like this:

        private static async Task ReceiveData()
        {
            ServiceReference1.Service1Client sc = new ServiceReference1.Service1Client();
            Stream stream = await sc.GetDataAsync();            

            using (var fs = File.Create(@"c:\tmp2\newfile.exe"))
            {
                int b;
                do
                {
                    b = stream.ReadByte();
                    fs.WriteByte((byte)b); 
                } while (b != -1);
            }
        }

As you can see, although the code is a bit messy, it’s not complex, and the bulk of the code is actually turning the Stream into a file (I’m sure there’s an easier way of doing this).

Configuration

The config files are the key here. The encoding and transfer mode need to be changed.

The service web.config:

    <bindings>
      <basicHttpBinding>
        <binding name="BasicStreaming" messageEncoding="Mtom" transferMode="Streamed"
                 closeTimeout="10:00:00"
                 />

      </basicHttpBinding>
    </bindings>

Create an endpoint for the service and bind it to above:

  <system.serviceModel>
    <services>
      <service name="FileService.Service1">
        <endpoint address="Service1.svc" binding="basicHttpBinding"
          bindingConfiguration="BasicStreaming" contract="FileService.IService1" />
      </service>
    </services>

So, the transfer mode is streamed, and the encoding is ‘Mtom’. Make sure that the endpoint is configured against the binding (otherwise it’ll use the default binding, repeatedly moan that it’s out of memory and mismatched for no apparent reason and you’ll spend ages wondering why).

The client config can be updated using the “Update Service Reference” option; however, double check what it adds.

The App.config changes from the client:

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicStreaming" closeTimeout="10:00:00" 
                    maxReceivedMessageSize="400000000" messageEncoding="Mtom" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:17065/Service1.svc/Service1.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicStreaming"
                contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>

The only real thing of note in the client is the `maxReceivedMessageSize`; this has to be big enough to take your largest file. Obviously, the timeout settings matter, but maybe if you’re taking 10 minutes to transfer then you’ve got bigger problems.

The End

That’s it – it all works neatly, and looks deceptively easy!