views:

388

answers:

2

Ok, I've got a strange problem. I am testing a usercontrol and have code like this:

[TestFixture]
public myTestClass : UserControl
{
    MyControl m_Control;

    [Test]
    public void TestMyControl()
    {
        m_Control = new MyControl();
        this.Controls.Add(m_Control);

        Assert.That(/*SomethingOrOther*/)
    }
}

This works fine, but when I change it to:

[TestFixture]
public myTestClass : UserControl
{
    MyControl m_Control;

    [Setup]
    public void Setup()
    {
        m_Control = new MyControl();
        this.Controls.Add(m_Control);
    }

    [TearDown]
    public void TearDown()
    {
        this.Controls.Clear();
    }

    [Test]
    public void TestMyControl()
    {
        Assert.That(/*SomethingOrOther*/);
    }
}

I get an Object Reference Not Set To An Instance of an Object. I even output to the console to ensure that the setup/teardown were running at the correct times, and they were... but still it isn't newing up the usercontrols.

edit> The exact code is:

[TestFixture]
public class MoneyBoxTests : UserControl
{
    private MoneyBox m_MoneyBox;
    private TextBox m_TextBox;

    #region "Setup/TearDown"
    [SetUp]
    public void Setup()
    {
        MoneyBox m_MoneyBox = new MoneyBox();
        TextBox m_TextBox = new TextBox();

        this.Controls.Add(m_MoneyBox);
        this.Controls.Add(m_TextBox);
    }

    [TearDown]
    public void TearDown()
    {
        this.Controls.Clear();
    }
    #endregion

    [Test]
    public void AmountConvertsToDollarsOnLeave()
    {
        m_MoneyBox.Focus();
        m_MoneyBox.Text = "100";
        m_TextBox.Focus();

        Assert.That(m_MoneyBox.Text, Is.EqualTo("$100.00"), "Text isn't $100.00");
    }

    [Test]
    public void AmountStaysANumberAfterConvertToDollars()
    {
        m_MoneyBox.Focus();
        m_MoneyBox.Text = "100";
        m_TextBox.Focus();

        Assert.That(m_MoneyBox.Amount, Is.EqualTo(100), "Amount isn't 100");
    }
}

I get the exception(s) at the respective m_MoneyBox.Focus() calls.

Solved - See Joseph's comments

A: 

You haven't said where you're getting the exception, which would help - what does the stack trace look like?

It's very odd (IME) to derive from UserControl when you create a test fixture. Aside from anything else, I don't know that NUnit is going to call Dispose for you at any appropriate point... what's the purpose of it here? Can you not make your tests run with a "plain" test fixture?

Jon Skeet
+1  A: 

I created a test case with exactly the same layout you presented here, but with a TextBox instead of a MyControl. I also added a constructor and a deconstructor and outputted all the various stages to the console to see the sequence of events. However, I never got an object reference exception.

In case you are interested, the sequence was [constructor called], [setup called], [test called], [tear down called]. The deconstruction never output anything to the screen for some reason.

My original thought was that the Controls property on myTestClass would not be initialized, but on my test it was, so I think it has something to do with your MyControl construction.

edit> I added the focus on my TextBox in my unit test as well but still no exception. Does your MoneyBox have any event handling going on behind the scenes during the Focus? That might be your culprit.

Joseph
! I figured it out. I very much appreciate your input. The problem was that I was re-declaring the moneybox/textbox in the setup (as opposed to JUST newing it).
SnOrfus
@SnOrfus:That is easy to do when you're promoting a local object to a class-wide object. Ironically you got it right in your pseudocode.
Autodidact