2

I am using TestCaseSource with NUnit. The below code generates IEnumerable of TestCaseData that represent an archive entry, which is an input for a test.

        private class GithubRepositoryTestCasesFactory
    {
        private const string GithubRepositoryZip = "https://github.com/QualiSystems/tosca/archive/master.zip";

        public static IEnumerable TestCases
        {
            get
            {
                using (var tempFile = new TempFile(Path.GetTempPath()))
                using (var client = new WebClient())
                {
                    client.DownloadFile(GithubRepositoryZip, tempFile.FilePath);

                    using (var zipToOpen = new FileStream(tempFile.FilePath, FileMode.Open))
                    using (var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read))
                    {
                        foreach (var archiveEntry in archive.Entries.Where(a =>
                            Path.GetExtension(a.Name).EqualsAny(".yaml", ".yml")))
                        {
                            yield return new TestCaseData(archiveEntry);
                        }
                    }
                }
            }
        }
    }

    [Test, TestCaseSource(typeof (GithubRepositoryTestCasesFactory), "TestCases")]
    public void Validate_Tosca_Files_In_Github_Repository_Of_Quali(ZipArchiveEntry zipArchiveEntry)
    {
        var toscaNetAnalyzer = new ToscaNetAnalyzer();

        toscaNetAnalyzer.Analyze(new StreamReader(zipArchiveEntry.Open()));
    }

The above code fails on the following line:

zipArchiveEntry.Open()

with an exception:

System.ObjectDisposedException "Cannot access a disposed object. Object name: 'ZipArchive'."

Is there any way to control the disposing of objects created for test data case?

Boris Modylevsky
  • 3,029
  • 1
  • 26
  • 42
  • How about remembering the created objects in a static variable and calling Dispose() of each in [TestFixtureTearDown](http://www.nunit.org/index.php?p=fixtureTeardown&r=2.4.8). – scher Jun 13 '16 at 09:05
  • @scher yes, it is possible, but would be less pretty. – Boris Modylevsky Jun 13 '16 at 09:23

1 Answers1

1

The problem is that the ZipArchive and its children are being disposed of at the end of the using block.

Try rigging up something like this within your fixture fixture:

// MyDisposable an IDisposable with child elements
private static MyDisposable _parent; 

// This will be run once when the fixture is finished running
[OneTimeTearDown]
public void Teardown()
{
    if (_parent != null)
    {
        _parent.Dispose();
        _parent = null;
    }
}

// This will be run once per test which uses it, prior to running the test
private static IEnumerable<TestCaseData> GetTestCases()
{
    // Create your data without a 'using' statement and store in a static member
    _parent = new MyDisposable(true);
    return _parent.Children.Select(md => new TestCaseData(md));
}

// This method will be run once per test case in the return value of 'GetTestCases'
[TestCaseSource("GetTestCases")]
public void TestSafe(MyDisposable myDisposable)
{
    Assert.IsFalse(myDisposable.HasChildren);
}

The key is to set the static member when creating the test case data, then disposing of it on the fixture tear down.

Robert Gowland
  • 7,677
  • 6
  • 40
  • 58