views:

18

answers:

1

Trying to use NUnit to test a method that adds an object to a queue, and throws an exception if the object's already been queued, but it fails because Queue.Contains() can't detect that the mock object's already in the queue.

The method under test is pretty simple:

public void Enqueue(ISomeInterface obj) {
    if (myQueue.Contains(obj)) {
        throw new InvalidOperationException("Already queued");
    }
    myQueue.Enqueue(obj);
}

And so's the test:

[Test()]
public void TestQueueAlreadyQueued()
{
    DynamicMock mock = new DynamicMock(typeof (ISomeInterface));
    ISomeInterface obj = (ISomeInterface) mock.MockInstance;
    queueulator.Enqueue(obj);
    try {
        queueulator.Enqueue(obj);
        Assert.Fail("Exception expected");
    } catch (InvalidOperationException e) {
        // test passed
    }
}

This fails -- myQueue.Contains(obj) always returns false, even though other tests prove that it is being added to the queue.

If I add to the test the following assertion --

    Assert.AreEqual(obj, obj);

-- it fails.

I've tried adding mock.ExpectAndReturn("Equals", true, obj) but that doesn't seem to do it -- I get "Too many calls to Equals / Expected: True / But was: False".

And frankly, I don't care how many times Equals is called -- I'm not trying to write a test that strict. Is there a simple way to set up Equals to behave "normally" here?

(And as a side note, is there a more advanced .NET mocking library that I should be using? I'm new to .NET, and after using things like Mockito in Java, NUnit.Mocks seems pretty 2005.)


ETA: I've started using Moq after seeing a favorable note from the author of Mockito; the code is a bit less cluttered and Contains() works, so that's a start. (Weirdly, AreEqual() still fails, though.)

A: 

I'm curious as to your motivation for using a mock here. It seems like your test would be simpler if you created a regular instance of a class that implements ISomeInterface. I guess in your case there must be no easy to instantiate concrete classes. If you can't get it to work with mocks, a solution would be to implement a concrete class just for this test.

I've not used nunit.mocks, I normally use Rhino Mocks which generally works pretty well, and also the Moq framework is popular.

Jonny Cundall
`myQueue` object is the system under test here. Why should David care about creating "regular" objects of `ISomeInterface`, if it is not needed here at all? That will be kind of violating rule of unit-test isolation.
A.
The test needs an object which implements ISomeInterface. Setting up a mock to do this clearly isn't working. So get it another way. There's no violation of isolation of the unit test that I can see.
Jonny Cundall
`ISomeInterface` has about twenty required properties on it, as well as a bunch of methods, none of which are relevant to the queuing behavior I'm trying to test. I don't want to clutter up the test either by (1) instantiating the real object, and having to set all those properties, or (2) rolling my own "mock" with stub implementations of all the properties and methods.
David Moles
@David now your approach makes sense to me.
Jonny Cundall