views:

156

answers:

3

I have the following class:

public class Script
{
    IPrinter _printer;

    public Script(IPrinter printer)
    {
        _printer = printer;
    }

    public void Print(TextWriter writer)
    {
        _printer.PrintComment(writer, "lolz");
        writer.WriteLine("omg this complicates things";
        _printer.PrintSpecial(writer);
        if (signoff)
            _printer.PrintComment(writer, "kthxbye");
    }
}

How would I setup a test to asserts that the printer methods are called in the correct order with the correct parameters?

I could manually create a 'fake' printer and do a state test on writer, but since the context is big (specially since script is also working with the writer) I'd like to avoid it.

I'm using nunit and rhino mocks. Any thoughts on architectural changes or mocking procedures to make this easier to test are appreciated. The real code I'm working with is unfortunately more complex - but this is the gist.

+3  A: 

You shouldn't need to test what order methods are called in. You should be testing to ensure that the proper effects have happened because you called the Print method.

However, if you really have to do this, I think the best way would be to create a mock IPrinter that stores the order functions were called, and the parameters that were passed, which can then be asserted in Tests.

Timothy Carter
Testing order of methods is called behavioural testing, and there are lots of reasons to do it, so I strongly disagree with your assertions. State testing is not the only way to write unit tests!
womp
A: 

You shouldn't need to test the compiler. If you were doing some kind of threading, I could see it... but in this case, with what you've posted, you aren't.

Like you said, you could create a mock printer, and test that the methods are called in order, but it'd be redundant.

You'd probably be better throwing exceptions in particular methods if the pre-conditions (ie. the previous methods) aren't called, but that alludes to there being a need for a refactoring into a single method.

Additionally, you could use the template method pattern to ensure that the methods are called in order, but unless you're going to have additional objects that will need to use that ordering, it'd be overkill.

SnOrfus
+4  A: 

You can't use static AAA syntax for verifying behaviours in Rhino unfortunately, you have to go back to the old style of "Replay" to do it AFAIK.

I'm not a rhino expert, I usually use Moq, but I think this is correct:

var mocks = new MockRepository();
var printer = mocks.DynamicMock<IPrinter>();
using (mocks.Ordered())
{
    printer.Expect(x => x.PrintComment());
    printer.Expect(x => x.PrintSpecial());
    printer.Expect(x => x.PrintComment());
}
printer.Replay();
Script = new Script(printer);

... Execute Test...

printer.VerifyAllExpectations();
womp
Change line three to 'using (mocks.Ordered())' to make the syntax correct.
TheDeeno
Ah, right. Ok, I updated it, thanks :)
womp