JUnit - should I assign null to resources in tearDown that were instantiated in setUp?

前端 未结 3 640
暖寄归人
暖寄归人 2021-01-11 11:07

I am reading one book about JUnit now and writer advises nulling resources in tearDown method. Why? Isn\'t this GC\'s job? Can it seriously make any harm?

Lets think

相关标签:
3条回答
  • 2021-01-11 11:36

    Yes, this can indeed be necessary.

    You see, JUnit will actually create a separate instance of the Test class for each test method, and the Junit3 test runner (not so with JUnit4) will keep these instances around until the entire test suite has finished.

    Therefore, if your (JUnit3) test class has fields that take up a lot of memory, you can easily run out of heap space when you have a large number of test methods. Of course, if those collections in your example code only ever contain a handful of short strings, it doesn't matter.

    0 讨论(0)
  • 2021-01-11 11:43

    JUnit 4.x style tests and test suites handle this differently than JUnit 3.x test suites.

    TL;DR: you should set fields to null in JUnit3-style tests but you do not need to in JUnit4-style tests.

    With JUnit 3.x style tests, a TestSuite contains references to other Test objects (which may be TestCase objects or other TestSuite objects). If you create a suite with many tests, then there will be hard references to all of the leaf TestCase objects for the entire run of the outermost suite. If some of your TestCase objects allocate objects in setUp() that take up a lot of memory, and references to those objects are stored in fields that are not set to null in tearDown(), then you might have a memory problem.

    In other words, for JUnit 3.x style tests, the specification of which tests to run references the actual TestCase objects. Any objects reachable from a TestCase object will be kept in memory during the test run.

    For JUnit 4.x style tests, the specification of which tests to run uses Description objects. The Description object is a value object that specifies what to run, but not how to run it. The tests are run by a Runner object that takes the Description of the test or suite and determines how to execute the test. Even the notification of the status of the test to the test listener uses the Description objects.

    The default runner for JUnit4 test cases, JUnit4, keeps a reference to the test object around only for the duration of the run of that test. If you use a custom runner (via the @RunWith annotation), that runner may or may not keep references to the tests around for longer periods of time.

    Perhaps you are wondering what happens if you include a JUnit3-style test class in a JUnit4-style Suite? JUnit4 will call new TestSuite(Class) which will create a separate TestCase instance per test method. The runner will keep a reference to the TestSuite for the entire life of the test run.

    In short, if you are writing JUnit4-style tests, do not worry about setting your test case's fields to null in a tear down (do, of course, free resources). If you are writing JUnit3-style tests that allocate large objects in setUp() and store those objects in fields of the TestCase, consider setting the fields to null.

    0 讨论(0)
  • 2021-01-11 11:48

    It depends what you consider a resource. Whilst heap space is a resource, you can probably get away with the GC cleaning up after you (YMMV).

    Things that might cause issues are Closables like database connections / open files and streams etc. which should always be closed after use to prevent nasties in long running code.

    I once had a situation that an integration test for some hibernate code didn't cleanup properly and resulted in some really strange errors. It took many hours to find and angered me so badly that I'll never make the same mistake again.

    0 讨论(0)
提交回复
热议问题