I have a case where my base class' constructor throws exceptions when providing invalid arguments.
Since I don't want to copy/paste the same test over and over again I'd like to ensure that the system under test actually implements IFoo, IBar and MyBaseClass.
On one hand it makes sense that my class will implement IFoo, IBar and MyBaseClass but on the other hand if my implementation changes I'll have one more test to maintain and if I'll make a convention out of this there might be some overhead when rearranging the inheritance hierarchy.

- 18,571
- 25
- 126
- 193
-
1I've recently been wondering the best way to approach this as well. Testing that it implements a particular interface/base class seems wrong as surely this is an implementation detail. As you said you might change this in the future. What you want to test is that behaviour is what you would expect. This sort of implies to me that there should be a test base class which all tests for specific implementations can extend and can be used to test the base functionality, so that each derived class is run through the base tests, which in your case would test the invalid arguments. – Sam Holder May 04 '11 at 14:53
-
does [this question](http://stackoverflow.com/questions/39003/nunit-how-to-test-all-classes-that-implement-a-particular-interface) help – Sam Holder May 04 '11 at 14:55
-
@SamHolder: Yes, but on the other hand the fact that you are inheriting from MyBaseClass provides some guarantees about the system under test. – the_drow May 04 '11 at 14:57
3 Answers
As a rule, I prefer to test behavior, not implementation. For example, I would make sure that I my SUT can do what IFoo and IBar offer. From a business perspective, it doesn't matter if MyClass implements IFoo or not. What is important, is that the objectUnderTest implements DoThis().
Assaf.

- 6,309
- 1
- 34
- 43
-
1@Assaf I think we agree on this, but the question is **how** do we write tests which will allow us to write the tests for the common parts once and have all implementations be tested by those tests, rather than repeat all of the same tests for each implementation. – Sam Holder May 05 '11 at 08:52
-
@Sam - I'm not sure I follow your question. I was implying that I don't actually write a test that verifies that an SUT has an interface or implements a method. I call the desired method and test the result. If you wish to test some common functionality, you should extract it to a separate class and test that (e.g. extract a WidgetCalculator class, that has a Execute() method). Does this help? – Assaf Stone May 05 '11 at 12:20
-
@Assaf. If you test common functionality by extracting to a different class and test that then you need to ensure the implementations use the common class (which is what the_drow is trying to do by testing that the inherit from a base class). If you don't do this then if you change the implementation to not use the common class, you will not have tests which cover the behaviour that was tested by the base class. otherwise you need to repeat the test for each derived class to ensure that for each implementation you are testing the behaviour. – Sam Holder May 05 '11 at 14:44
-
Imagine I have a Method DoThis() which I want to verify does something . So I create a test to check it. Now imaging DoThis comes from an interface, and I have 100 classes that all implement DoThis(). I have to write 100 tests for this. If I put DoThis in a base class I can test it once, but I now have the problem that if I change the implementation of one of the derived classes so that it doesn't inherit from base class then DoThis is now not tested. We would like a method where the test for DoThis is written once, and each implementation can be run through the test. – Sam Holder May 05 '11 at 14:50
-
Ok. Let's say we have two classes: **Service** and **Engine**. Service.DoThis() calls Engine.Execute(). I will have a test that checks the behavior of Service.DoThis() which stubs (but doesn't check the implementation of) Engine.Execute(). I will _also_ have a test that checks the behavior of Engine.Execute(). This should give you full coverage. – Assaf Stone May 05 '11 at 15:13
-
@Assaf, this is great and perfectly valid and probably what you should do, but slightly orthoganal to the question. See my answer for my take on it. I'll be updating it later with a bit more info as well. – Sam Holder May 05 '11 at 15:39
-
I have updated my answer to demonstrate what I meant about testing the implementation of the interface without depending on the implementation and without repeating the tests, using many implementations of IList as the example. Hope this makes things clearer. – Sam Holder May 05 '11 at 17:50
I think you can solve this by using an abstract base class which contains some of the tests, with an abstract method which gets the specific implementation.
This still require a little code in each concrete implementation test class but should ensure that if you change the implementation away from a base class your constructors are still tested.
i have done something similar just now to test a method which for many implementations is a no op (it just returns what it was given), but for some implementations it does something, and so the no op code tests are in a single base class with an abstract method to get the object to test (gets an instance of the interface that the no op method lives in), and the concrete implementations which should just be a no op extend that class and override the abstract method to return an instance of the class which we want to test the methods on.
this helped me solve my problem, hopefully it will help you too.
public abstract class BaseClass
{
public abstract void CallConstructor(SomeType arg1, SomeType2 arg2);
[Test]
public void Constructor_WhenArg1IsNull_ArgumentNullExceptionIsThrown()
{
Assert.Throws<ArgumentNullException>(()=>CallConstructor(null, new SomeType2()));
}
[Test]
public void Constructor_WhenArg2IsNull_ArgumentNullExceptionIsThrown()
{
Assert.Throws<ArgumentNullException>(()=>CallConstructor(new SomeType(), null));
}
}
[TestFixture]
public class ConcreteImplementation1Tests : BaseClass
{
public override void CallConstructor(SomeType arg1, SomeType2 arg2)
{
new ConcreteImplementation1(arg1,arg2);
}
}
[TestFixture]
public class ConcreteImplementation2Tests : BaseClass
{
public override void CallConstructor(SomeType arg1, SomeType2 arg2)
{
new ConcreteImplementation2(arg1,arg2);
}
}
in addition to this the same technique can be used for testing common
functionality for all classes that implement an interface. Using IList as an example:
public abstract class ListImplementationsCommonTests
{
public abstract IList GetListImplementation();
[Test]
public void Add_WhenValidItemIsAdded_ItCanBeFound()
{
IList list = GetListImplementation();
object item = new Object();
list.Add(item);
Assert.That(list.Contains(item));
}
[Test]
public void Add_WhenNullIsAdded_ArgumentNullExceptionIsThrown()
{
IList list = GetListImplementation();
Assert.Throws<ArgumentNullException>(()=>list.Add(null));
}
...
//more common tests
...
}
Then each implementation of IList (so ArrayList, LinkedList, DoubleLinkedList, SortedList etc etc) could then be tested with the same code without needing to repeat the same tests again and again:
[TestFixture]
public class ArrayListTests: ListImplementationCommonTests
{
public override IList GetListImplementation()
{
return new ArrayList();
}
...
//Extra specific tests for the ArrayList
}
[TestFixture]
public class LinkedListTests: ListImplementationCommonTests
{
public override IList GetListImplementation()
{
return new LinkedList();
}
...
//Extra specific tests for the LinkedList
}
[TestFixture]
public class SortedListTests: ListImplementationCommonTests
{
public override IList GetListImplementation()
{
return new SortedList();
}
...
//Extra specific tests for the SortedList
}

- 32,535
- 13
- 101
- 181
Test the implementations of IFoo and IBar separate from the Class that implements them. So you don't have to test it, when you test the implementing class.
For MyBaseClass (if it is declared as MustInherit) I would create a test mock (that inherits from MyBaseClass and is located in the test project) and test all what is done in MyBaseClass.

- 2,712
- 2
- 28
- 47