9

Does NUnit dispose of objects that implement IDisposable on cleanup? I realize there are various ways I can get an object disposed of in a method, but, for example, if the method fails prior to the object being disposed - will NUnit take care of it? (For reference, i'm on v2.6+)

The specific reason i'm asking is for a case where an object that implements IDisposable is created, but I am asserting that an exception is thrown upon creation. If the test fails - and the object is created, I do not want to run into memory leak problems.

Example:

//Will the StreamReader instance here be disposed 
//Of if the assertion fails, and the instance is created?
Assert.Throws<Exception>(() => new StreamReader(filename));

I realize that this will work:

Assert.Throws<Exception>(() => 
{
    using (StreamReader sr = new StreamReader(filename)) { }
}

But it just seems like unnecessary code if NUnit will take care of disposing when necessary.

user2338408
  • 182
  • 1
  • 11
  • 4
    I can't see a way that NUnit would reliably know that nothing else references the IDisposable so that it can safely dispose it. I'd not want to run into a case where an assert erroneously disposes referenced objects. It shouldn't be very tricky to test though, just make a dummy disposable object, set a breakpoint in dispose and check the stack trace where it's called from. – Joachim Isaksson Apr 26 '16 at 14:53
  • @JoachimIsaksson I'm wondering if maybe NUnit forces disposing of all objects at the end of each test case since tests _shouldn't_ be reliant upon each other, and anything created in a test case can theoretically be disposed of as soon as the test is completed. I'm fine with keeping with standard IDisposable practices, but I'm wondering if anybody has a definitive answer on this. – user2338408 Apr 26 '16 at 15:00
  • 1
    I agree with @Joachim. Just to add, adding a `[TearDown]` to dispose of an object is probably the way to go, rather than the `Assert.Throws(using...)` in your question. – Chris Apr 26 '16 at 15:01
  • @JoachimIsaksson just saw the extended response. I'll run a test on it when I get a chance and reply to this with the results. Thanks for the help. – user2338408 Apr 26 '16 at 15:08
  • @Chris, The problem I see with using a [TearDown] method for this is that I am expecting an exception, so I would only need to dispose of the instance if the exception is not thrown. I would think that getting the reference to object in the off chance that the creation it is created would be more of a pain than just popping it into a using block. – user2338408 Apr 26 '16 at 15:08
  • Surely that's just an instance variable? You can check for failure by looking at `TestContext`. But it doesn't really matter - I guess it's more a personal preference! =) – Chris Apr 26 '16 at 15:13

1 Answers1

14

No, NUnit will not dispose your objects when used that way. NUnit 3.x will dispose test fixtures that are IDisposable, but that is it.

You state that it seems unnecessary to dispose because NUnit can do it for you, but that is incorrect. In the code in your example, it looks to you like you are passing NUnit an IDisposable object, but in fact you are passing a delegate/lambda/code block that happens to contain an IDisposable object.

You will notice that the signature for Assert.Throws is;

public static TActual Throws<TActual>(TestDelegate code) where TActual : Exception

Notice that it takes a TestDelegate, not an object. TestDelegate is just a void delegate,

public delegate void TestDelegate();

You are reading your code as if you are passing in a StreamReader, but you are actually passing in a delegate, or in other words a method that NUnit calls. NUnit doesn't know or care what you do in that method. Like any other method, it is up to you to dispose objects you create.

Rob Prouse
  • 22,161
  • 4
  • 69
  • 89