views:

5256

answers:

13

Hello

I was wondering what the best practice is for unit testing abstract classes and classes that extend abstract classes.

Should I test the abstract class by extending it and stubbing out the abstract methods and then test all the concrete methods? Then only test the methods I override and the abstract methods in the unit tests for objects that extend my abstract class.

Should I have an abstract test case that can be used to test the methods of the abstract class and extend this class in my test case for objects that extend the abstract class?

EDIT: My abstract class has some concrete methods.

I would be interested to see what people are using.

Thanks Paul

A: 

Why would you test an abstract class? You either have concrete classes that extend it that should be tested or you aren't using it which means it should be removed from the code base.

Update: I can see where you might be building a framework that others would be extending. In that case you might not have a concrete class, but I'd consider either providing a concrete default implementation or using aggregation / composition to test the base functionality.

Paul Croarkin
+1  A: 

I would argue against "abstract" tests. I think a test is a concrete idea and doesn't have an abstraction. If you have common elements, put them in helper methods or classes for everyone to use.

As for testing an abstract test class, make sure you ask yourself what it is you're testing. There are several approaches, and you should find out what works in your scenario. Are you trying to test out a new method in your subclass? Then have your tests only interact with that method. Are you testing the methods in your base class? Then probably have a separate fixture only for that class, and test each method individually with as many tests as necessary.

casademora
I didn't want to retest code I had already tested thats why I was going down the abstract test case road. I am trying to test all the concrete methods in my abstract class in one place.
Paul Whelan
I disagree with extracting common elements to helper classes, at least in some (many?) cases. If an abstract class contains some concrete functionality I think it's perfectly acceptable to unit test that functionality directly.
Seth Petry-Johnson
A: 

If the concrete methods invoke any of the abstract methods that strategy won't work, and you'd want to test each child class behavior separately. Otherwise, extending it and stubbing the abstract methods as you've described should be fine, again provided the abstract class concrete methods are decoupled from child classes.

Jeb
+1  A: 

I suppose you could want to test the base functionality of an abstract class... But you'd probably be best off by extending the class without overriding any methods, and make minimum-effort mocking for the abstract methods.

Ace
+4  A: 

To make an unit test specifically on the abstract class, you should derive it for testing purpose, test base.method() results and intended behaviour when inheriting.

You test a method by calling it so test an abstract class by implementing it...

+6  A: 

What I do for abstract classes and interfaces is the following: I write a test, that uses the object as it is concrete. But the variable of type X (X is the abstract class) is not set in the test. This test-class is not added to the test-suite, but subclasses of it, that have a setup-method that set the variable to a concrete implementation of X. That way I don't duplicate the test-code. The subclasses of the not used test can add more test-methods if needed.

Mnementh
+15  A: 

Write a Mock object and use them just for testing. They usually are very very very minimal (inherit from the abstract class) and not more.Then, in your Unit Test you can call the abstract method you want to test.

You should test abstract class that contain some logic like all other classes you have.

Daok
Damn, I have to say this is the first time I've ever agreed with the idea of using a mock.
Jonathan Allen
Daok: Could you please provide a simple example? I don't know, why I should use a Mock instead of a minimal class. Or did I misunderstand you? Thanks in advance!
furtelwart
Mocks simply let you avoid having to write a stub implementation of the abstract base class, in this use they are far and away the most sensible choice assuming you are happy to take the dependency on a mocking framwork
ShuggyCoUk
Just trying to work this out...so you create the mock as a subclass. Is the mock generated on the fly? If so, how do you reach inside to test all the abstract's innards? If the mock is hard-coded, does any testcode go inside the mock's declaration to make the abstract do a work-out. Just wondering. I tend to do what Mnementh does.
JW
+2  A: 

This is the pattern I usually follow when setting up a harness for testing an abstract class:

public abstract class MyBase{
  /*...*/
  public abstract void VoidMethod(object param1);
  public abstract object MethodWithReturn(object param1);
  /*,,,*/
}

And the version I use under test:

public class MyBaseHarness : MyBase{
  /*...*/
  public Action<object> VoidMethodFunction;
  public override void VoidMethod(object param1){
    VoidMethodFunction(param1);
  }
  public Func<object, object> MethodWithReturnFunction;
  public override object MethodWithReturn(object param1){
    return MethodWihtReturnFunction(param1);
  }
  /*,,,*/
}

If the abstract methods are called when I don't expect it, the tests fail. When arranging the tests, I can easily stub out the abstract methods with lambdas that perform asserts, throw exceptions, return different values, etc.

Will
+1  A: 

One of the main motivations for using an abstract class is to enable polymorphism within your application -- i.e: you can substitute a different version at runtime. In fact, this is very much the same thing as using an interface except the abstract class provides some common plumbing, often referred to as a Template pattern.

From a unit testing perspective, there are two things to consider:

  1. Interaction of your abstract class with it related classes. Using a mock testing framework is ideal for this scenario as it shows that your abstract class plays well with others.

  2. Functionality of derived classes. If you have custom logic that you've written for your derived classes, you should test those classes in isolation.

edit: RhinoMocks is an awesome mock testing framework that can generate mock objects at runtime by dynamically deriving from your class. This approach can save you countless hours of hand-coding derived classes.

bryanbcook
+4  A: 

If your abstract class contains concrete functionality that has business value, then I will usually test it directly by creating a test double that stubs out the abstract data, or by using a mocking framework to do this for me. Which one I choose depends a lot on whether I need to write test-specific implementations of the abstract methods or not.

The most common scenario in which I need to do this is when I'm using the Template Method pattern, such as when I'm building some sort of extensible framework that will be used by a 3rd party. In this case, the abstract class is what defines the algorithm that I want to test, so it makes more sense to test the abstract base than a specific implementation.

However, I think it's important that these tests should focus on the concrete implementations of real business logic only; you shouldn't unit test implementation details of the abstract class because you'll end up with brittle tests.

Seth Petry-Johnson
+3  A: 

one way is to write an abstract test case that corresponds to your abstract class, then write concrete test cases that subclass your abstract test case. do this for each concrete subclass of your original abstract class (i.e. your test case hierarchy mirrors your class hierarchy). see Test an interface in the junit recipies book: http://safari.informit.com/9781932394238/ch02lev1sec6.

also see Testcase Superclass in xUnit patterns: http://xunitpatterns.com/Testcase%20Superclass.html

Ray Tayek
A: 

but what if my abstract class looks like this:

public abstract class AbstractDAO, KeyClass> implements IDAO

I can crate mock impl, but I will have to put some EntityClass in <> thus unit test of abstrat dao will be depended from on of my entity classes

and that sucks

+1  A: 

There are two ways in which abstract base classes are used.

1/ You are specializing your abstract object, but all clients will use the derived class through it's base interface.

2/ You are using an abstract base class to factor out duplication within objects in your design, and clients use the concrete implementations through their own interfaces.

If you have the first situation, then you actually have an interface defined by the virtual methods in the abstract class that your derived classes are implementing. You should consider making this a real interface, changing your abstract class to be concrete, and take an instance of this interface in it's constructor. Your derived classes then become implementations of this new interface. This means you can now test your previously abstract class using a mock instance of the new interface, and each new implementation through the now public interface. Everything is simple and testable.

If you have the second situation, the your abstract class is working a helper class. Take a look at the functionality it contains. See if any of it can be pushed onto the objects that are being manipulated to minimize this duplication. If you still have anything left, look at making it a helper class that your concrete implementation take in their constructor and remove their base class. This again leads to concrete classes that are simple and easily testable.

As you can tell "I prefer a complex network of simple objects to a simple network of complex objects" -- to quote James Ross

Nigel Thorne