views:

49

answers:

3

Is there any special support when you come to test callbacks with NUnit? Or some kind of of "best practice" which is better than my solution below?

I just started writing some tests and methods, so I have still full control - however I think it might be annoying if there are better ways to test callbacks thoroughly, especially if complexity is increasing. So this is a simple example how I am testing right now:

The method to be tested uses a delegate, which calls a Callback function, for instance as soon as a new xml element is being discovered in a stream. For testing purpose I pass the NewElementCallback Method to the delegate and store the arguments content in some test classes properties when the function is called. These properties I use for assertion. (Of course they are being reset in the test setup)

[Test]
public void NewElement()
{
    String xmlString = @"<elem></elem>";

    this.xml.InputStream = new StringReader(xmlString);
    this.xml.NewElement += this.NewElementCallback;

    this.xml.Start();

    Assert.AreEqual("elem", this.elementName);
    Assert.AreEqual(0, this.elementDepth);
}

private void NewElementCallback(string elementName, int elementDepth)
{
    this.elementName = elementName;
    this.elementDepth = elementDepth;
}
A: 

There isn't anything special in NUnit for this that I know of. I test these things the same way you do. I do tend to put the callback method and the state it stores on another class. I think it makes it a bit cleaner, but it isn't fundamentally different.

Mike Two
A: 

From your example, I can't tell exactly what you're trying to do, however, NUnit doesn't provide any specific way to test this kind of thing, however this link should present you some ideas on how to start unit-testing asynchronous code: Unit Testing Asynchronous code

warriorpostman
+3  A: 

You could avoid the need for private fields if you use a lambda expression, that's how I usually do this.

[Test]
public void NewElement()
{
    String xmlString = @"<elem></elem>";
    string elementName;
    int elementDepth;

    this.xml.InputStream = new StringReader(xmlString);
    this.xml.NewElement += (name,depth) => { elementName = name; elementDepth = depth };

    this.xml.Start();

    Assert.AreEqual("elem", elementName);
    Assert.AreEqual(0, elementDepth);
}

it makes your tests more cohesive and having fields on any test class is always asking for disaster!

Jeffrey Cameron
I still prefer putting the handler and state on another class. While the lambda and local variables removes the need for fields it still leaves the test method a bit cluttered.
Mike Two
I like the lambda expression in this case because you do not pollute yout test class with separate callback methods which actually do not really fit into the test class. Maybe more complex testes might make use of an own class Mike, however I can not think about a case were this would make sense yet.
Vash