TDD Teaser #2 - Think you know NUnit?

I recently concluded a TDD with ASP.NET presentation in Cleveland with several TDD Teaser problems for the audience.  The idea proved to be a lot of fun so I decided to repost the problems on my blog.

The Rules:

  1. Prize (a Thycotic keyring light) to be mailed to the first comment with the correct answer on this blog post with valid contact information.
  2. My definition of the problem is the correct one. :)  Other answers might be right but won't win the prize.
  3. I will post the answer within a few days.

What is wrong with running the following Test?

1using NUnit.Framework;
2
3namespace UnitTests.BadCode
4{
5  [TestFixture]
6  public abstract class Problem2
7  {
8    [Test]
9    public virtual void TestSomething()
10    {
11       RedHerring @int = new RedHerring();
12       Assert.AreEqual(1, @int.BogusNumber);
13    }
14  }
15  public class RedHerring
16  {
17      public int BogusNumber;
18  }
19}

UPDATE:  I am looking specifically for an error rather than a test failure.

Winner: Kirk Marple

Answer & Discussion (click and drag your mouse to see the answer)
Duncan - you are right. The value of BogusNumber would initialize to zero as it is an instance variable. I was looking for an error though not a test failure.

Answer:
NUnit creates an instance of the TestFixture labeled classes when it runs and calls their Test labeled methods. It cannot create an instance of an abstract class so it will ignore it in the NUnit GUI (Problem2 won't even appear). However using the NUnitAddIn and selecting to run the individual Test will cause the error that the instance can't be instantiated. Abstract classes are very useful when refactoring your test suites. We get bitten by this little quirk all the time on our projects when an inherited test fail in the unit test report and the first thing we do is try to run the individual test on our workstations.

Well done to Kirk for the first correct answer.

Well done also to Ron Buckton and Vishal Narayan Saxena for elaborating on the answer!

5 Comments

  • The @ is being used to escape the keyword int so that it can be used as a variable.



    RedHerring.BogusNumber would initialise to 0.



    The test would fail.



    duncangodwin@nospamplease.dial.pipex.com.

  • Problem2 is an abstract class, and therefore can't be instantiated by itself.



    I'd bet that NUnit couldn't create the TestFixture for Problem2 and TestSomething wouldn't ever get called.



    kirk(nospam)@agnostic-media.com

  • Too late to solve it first but i'll agree with Kirk, NUnit creats an instance of any object declared as a [TestFixture], and you cannot create instances of abstract classes. Sure, if it were not abstract the TestSomething method would fail, but it would fail at the Assert rather than on run. Any [Test] methods on such a class would fail, regardless of whether they should succeed or not.



    I'd say you could make a the problem a little more difficult by *not* calling the business object being tested "Red Herring" ;)



    (rbuckton(at)chroniclesdesign.com)

  • I should correct that its not specifically a failure but rather that the code never gets called. NUnit (or at least the TestDriven.NET NUnit Addin) silently skips types it cannot create that are flagged with [TestFixture]. I've created a few abstract classes marked as [TestFixture] to do unit tests on database logic code (using a ServicedComponent to rollback tests and prevent data modifications). So there's no "error", the tests just won't be run.



    If a developer were to subclass Problem2 the test would run under the subclassed type.

  • The problem with the code is with the below lines



    [TextFixture]

    public abstract class Problem2



    because Problem2 is defined as abstract and

    to run a test against a class, Nunit needs to instancate the class to work on. it needs something to call methods on and get values back if needed. Nunit needs a real live object. In the case of abstract classes there’s no way to do this.



Comments have been disabled for this content.