.NET - Interfaces and unit testing

4.15 , 0 Comments

I have been using SharpDX lately. SharpDX is a .NET wrapping for a DirectX API. It allows developers to create DirectX applications only by using .NET. It supports Windows Moden UI, Desktop and Windows Phone 8. Devplanet has a nice tutorial about creating a simple cube drawing app with SharpDX.

On one day I was writing unit tests for SharpDX code. My code was using SharpDX.Toolkit.Input.PointerService class. This class allows developer to read active touches from screen. My class which contained touch handling code had a dependency on IPointerService interface. I thought this would be enough to support unit testing, but oh-boy how wrong I was.

What's wrong with IPointerService

public interface IPointerService 
{
     ///     
     /// Gets the current state of the pointer
     ///
     PointerState GetState();
     ///
     /// Fills the provided object with the current pointer state information 
     ///
     void GetState(PointerState state); 
 }

There is the interface definition. Where things starts to go wrong is the GetState method and its return type. When IPointerService is used it will always return a PointerState type. We cannot mock the whole returning type. However there is still hope! If PointerState contains overridable functions we can mock those.

public sealed class PointerState
{
     // this class can be reused several times to avoid garbage generation 
     // it represents a future-proof wrapper around a simple list of pointer points 

     ///    
     /// Initializes a new instance of class
    ///
     public PointerState()
    {
          Points = new List<PointerPoint>();  
    } 

     // we expose a concrete List as it's Enumerator is a struct and iteration will not generate garbage, 
     // however, the collection is mutable and it is responsibility of user-developer to avoid its change 

     ///
     /// The collection of that were raised at some specific time      ///      public List<PointerPoint> Points { get; private set; } 
}

PointerState is a sealed class which contains a getter for points list. How about if we put fake points inside that Points collection? Well the setter is private so its not doable.

How about PointerPoint? We cannot put it inside Points collection but lets still see it:

[StructLayout(LayoutKind.Sequential)]
public struct PointerPoint : IEquatable 

     ///
     /// The type of event that represents current pointer point      ///      public PointerEventType EventType { get; internal set; } 

     ///
     /// The device type that raised the event.      ///      public PointerDeviceType DeviceType { get; internal set; } 

     ///
     /// An unique identifier of this pointer input point.      ///      public uint PointerId { get; internal set; } 

     ///
     /// The location of pointer input point in client coordinates.      ///      public Vector2 Position { get; internal set; }

     ...
}

Well that follows the PointerState design.

How things could be fixed

IPointerService should return an IPointerState interface and IPointerState should return an list of IPointerPoints, so remember to think of the whole chain when designing interfaces. This whole thing would be solved by using TDD on design phase.

The best way to predict the future is to implement it.

0 kommenttia: