1

I know this is kindof a generic programming question, but I have Googled it on several occasions in the past and I have never found a firm answer.

Several months back I had a conversation about Interfaces with a senior engineer at another company. He said he prefers to write Interfaces for everything because (among other things) it allows him to "test to the interface". I didn't think about the phrase too much at the time, (if I had I would have just asked him to explain!) but it confused me a bit.

I think this means he would write a unit test based on the interface, and that test would then be used to analyze every implementation of the interface. If thats what he meant, it makes sense to me. However, that explanation still left me wondering what the best practice would be when, for example, one of your implementations exposes additional public methods that are not defined in the interface? Would you just write an additional test for that class?

Thanks in advance for any thoughts on the subject.

William Smith
  • 1,949
  • 4
  • 25
  • 45
  • 2
    Writing to interfaces makes it extremely simply to write mocks for unit testing. – crush Jan 17 '14 at 16:12
  • 5
    This is a nice fit for [programmers.SE](http://programmers.stackexchange.com/) , but over here it's not quite a fit – Caffeinated Jan 17 '14 at 16:12
  • One could argue that every public method should derive from some interface. – crush Jan 17 '14 at 16:15
  • @crush one could also argue that the sky is green, it doesn't make it right though ;) – Joe Jan 17 '14 at 16:17
  • Although by allowing every public method to derive from an interface, you can separate dependencies very well. Obviously you would only want to do that where something has the possibility to BE a dependency.. – Dan Jan 17 '14 at 16:37

3 Answers3

3

Are you sure he said test to the interface and not program to the interface?

In very simple terms what program to an interface means is that your classes should not depend on a concrete implementation. They should instead depend on an interface.

The advantage of this is that you can provide different implementations to an interface, and that enables you to unit test your class because you can provide a mock/stub to that interface.

Imagine this example:

public class SomeClass{
    StringAnalyzer stringAnalizer = new StringAnalizer();
    Logger logger = new Logger();

    public void SomeMethod(){
        if (stringAnalyzer.IsValid(someParameter))
        {
            //do something with someParameter
        }else
        {
            logger.Log("Invalid string");
        }       
    }
}

Contrast that with this one:

class SomeClass
{
    IStringAnalyzer stringAnalizer;
    ILogger logger;

    public SomeClass(IStringAnalyzer stringAnalyzer, ILogger logger)
    {    
        this.logger = logger;
        this.stringAnalyzer = stringAnalyzer;
    }


    public void SomeMethod(string someParameter)
    {
        if (stringAnalyzer.IsValid(someParameter))
        {
            //do something with someParameter
        }else
        {
            logger.Log("Invalid string");
        }
    }
}

This enables you to write tests like this:

[Test]
public void SomeMethod_InvalidParameter_CallsLogger
{
    Rhino.Mocks.MockRepository mockRepository = new Rhino.Mocks.MockRepository();
    IStringAnalyzer s = mockRepository.Stub<IStringRepository>();
    s.Stub(s => s.IsValid("something, doesnt matter").IgnoreParameters().Return(false);
    ILogger l = mockRepository.DynamicMock<ILogger>();
    SomeClass someClass = new SomeClass(s, l);
    mockRepository.ReplayAll();

    someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false");

    l.AssertWasCalled(l => l.Log("Invalid string"));
}

Because in the second example you depend on interfaces and not concrete classes, you can easily swap them by fakes in your tests. And that is only one of the advantages, in the end it boils down to that this approach enables you to take advantage of polymorphism and that is useful not only for tests, but for any situation where you may want to provide alternative implementations for the dependencies of your class.

Full explanation of the example above can be found here.

Rui
  • 4,847
  • 3
  • 29
  • 35
  • The thing is, if he had said "program to the interface" it would have made complete sense to me. – William Smith Jan 17 '14 at 16:43
  • @WilliamSmith He probably meant program to the interface or he was referring to the fact that you should focus on the [public methods of your class when you are testing it](http://stackoverflow.com/questions/105007/should-i-test-private-methods-or-only-public-ones). – Rui Jan 17 '14 at 16:53
2

Testing to an interface - while I've never heard that terminology before - would basically mean that while you test a concrete implementation of your interface, you only test the methods provided BY that interface. For example, consider the following classes:

interface A
{
    int MustReturn3();
}

class B : A
{
   public int MustReturn3()
   {
      return Get3();
   }
   public int Get3()
   {
      return 2 + 1;
   }
}

When you want to test an implementation of A, what do you test? Well, my implementation is B. I want to make sure that B accomplishes the tasks of A as it is supposed to.

I don't really care about testing Get3(). I only care that MustReturn3() will follow the interface detail, ie, it will return 3.

So I would write a test like so:

private A _a;

[TestInitialize]
public void Initialize()
{
    _a = new B();
}

[TestMethod]
public void ShouldReturn3WhenICallMustReturn3()
{
    Assert.AreEqual(3, _a.MustReturn3());
}

This ensures I am not testing any implementation detail; I'm only testing what the interface tells me that the class implementation should do.

This is how I write my unit tests, actually. You can see a real working version of a test like this here.

Dan
  • 10,282
  • 2
  • 37
  • 64
1

It makes unit testing easier as you can easily mock interfaces to return you data needed for the code your testing.

yoozz
  • 247
  • 2
  • 15