3

I am writing a test class for an implementation of an interface, and want to test my implementation against another implementation (i.e. to ensure consistency). The test methods will then test each of the interface methods to check this.

To do this I could:

a) create a private static constant fields of the original implementation and my new implementation:

public class MyImplTest extends TestCase {

  private static OldImpl _original;
  private static MyImpl _myImpl;
  static {
    // instantiate _original and _myImpl
  }

  // My tests
}

b) create private fields of the two implementations, and instantiate them using setUp():

public class MyImplTest extends TestCase {
  private OldImpl _original;
  private MyImpl _myImpl;

  public void setUp(){
    // instantiate _original and _myImpl
  }

  // My tests
}

Is either of these preferred / considered good style? My instinct suggests (b), but I want to create quite large objects, and setUp() gets run for each testSomething() method in the TestCase, so both _original and _myImpl would be created multiple times.

FWIW, I'm using JUnit 3.

amaidment
  • 6,942
  • 5
  • 52
  • 88
  • For future readers, this [SO question](http://stackoverflow.com/questions/512184/best-practice-initialize-junit-class-fields-in-setup-or-at-declaration) may also be helpful. – amaidment Jun 22 '12 at 12:38

1 Answers1

7

Using the setup method will cause the initialization code to run before each test. Static initializers will run once (and only once) when the class is first loaded, which means they will execute only once per test run.

It is often a better idea to initialize everything fresh for each test, just to remove the ability of the state of any objects from one test affecting other tests.

The only time I have found using static initialization to be useful was when I was writing integration (not unit) tests and my class under test was expensive to construct. I was certain that the object was stateless though so that tests could not interfere with each other. If you aren't certain, it is better to use the setup() method to be safe.

Sean Reilly
  • 21,526
  • 4
  • 48
  • 62
Jesse Webb
  • 43,135
  • 27
  • 106
  • 143
  • Thanks - that's a good point, but in my case, both OldImpl and MyImpl are immutable – amaidment May 10 '12 at 14:24
  • @JesseWebb: Hahaha — I was just about to submit *exactly* that answer, and you beat me to it. What are the odds? (P.S. long time no see!) – Sean Reilly May 10 '12 at 14:27
  • Also note that if your setup is relatively simple (such as just constructing an object) you can just instantiate the fields inline, and skip the ceremony of a setup method. – Sean Reilly May 10 '12 at 14:29
  • Also - where does the idea that 'static initialization will only run before the test class runs all tests' come from? I don't find this to be the case... – amaidment May 10 '12 at 14:29
  • @amaidment - if your objects are expensive to initialize and they are immutable, you can use static initialization, but in most cases, using the setup() method is prefered. – Jesse Webb May 10 '12 at 14:30
  • @JesseWebb - thanks. I'd accept this, but I'm not sure about static initialization only occurring when all tests are run. I understood that static fields were initialized when the class was loaded - i.e. before any (or all) of the test methods were run. – amaidment May 10 '12 at 14:36
  • @amaidment: That's definitely what happens. In fact, it's a given based on the java memory model. All static fields for any class are only initialised once (per class loader) when the class is first loaded. – Sean Reilly May 10 '12 at 14:39
  • @amaidment - it depends on which test runner you are using. For instance, I believe the Surefire runner used by Maven keeps the same TestClass instance for all unit tests in the file but some runners may instantiate a brand new test class for each single test, which mean using static initialization vs. the setup() method would not make any difference what-so-ever. I still recommend using the setup() method unless doing it the other way is **WAY** less expensive. – Jesse Webb May 10 '12 at 14:41
  • @JesseWebb - thanks, that's helpful colour. Aside from that, and in the interests of accuracy, would you change your second sentence to 'The static initialization will only run when the test class is loaded.'? (I would do this, but it seems a little cheeky to amend someone else's answer to my question...) – amaidment May 10 '12 at 14:44
  • @Jesse: Surefire should construct a separate instance of the test class for each run as well. Surefire's behaviour is the same as vanilla junit for details like this (otherwise tests would break). It's TestNG that famously doesn't construct a testcase instance for each test method. – Sean Reilly May 10 '12 at 14:48