Lessons learned about upgrading from NUnit 2.x to 3.x

Our current project has been spurred to move from NUnit version 2.6.4 to version 3.6 for .NET Core compatibility.  Along the way we learned about some key differences, some minor, some more interesting:

Ignore attributes

With NUnit 3.x, [Ignore] attributes must specify a reason. So, everywhere we had this before a test method:

[Ignore]

we adjusted it to:

[Ignore("Reason")]

ExpectedException attributes

We had been using the ExpectedException attributes to evaluate proper error handling.  Here is a typical example:

        [Test]
        [ExpectedException(typeof(OurCustomException), ExpectedMessage = "Some Exception Text")]
        public void Method_ThrowsExpectedException()
        {
            .
            .
            .
            testedObject.TestedMethod();
        }

The ExpectedException attribute is no longer supported.  Instead, there are a couple of new ways to evaluate Exceptions: 

  • ex = Assert.Throws<ExceptionType>(() => testedObject.TestedMethod())
  • Assert.That(testedObject.TestedMethod(), Throws<ExceptionType>)

In our case, we wanted to test, not only the Exception Type but also the error message.  So, we implemented the first option.  Here is an example:

        [Test]
        public void Method_ThrowsExpectedException()
        {
            .
            .
            .
            ex = Assert.Throws<OurCustomException>(() => testedObject.TestedMethod());
            Assert.That(ex.Message, Is.EqualTo("Some Exception Text");
        }

NUnit no longer sets work directory to \bin folder

At times, our tests count on finding certain files within the project folder structure.  For example, some logging features normally write to a standard logging folder, but in a test context we point them to write to a folder in the project structure.  This behavior depended on the test runner changing the working directory to the \bin folder, which NUnit 2.x used to do.  NUnit 3 doesn't do that anymore.  So, we need to change the working directory as a setup step in order for the existing tests to continue to function.  Since, the affected test projects were Specflow-based, we added this code in one of the step files:

        [BeforeTestRun]
        public static void TestRunSetup()
        {
            var dir = Path.GetDirectoryName(typeof(CurrentClassName).Assembly.Location);
            Environment.CurrentDirectory = dir;
        }