2

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.)

David Moles
  • 48,006
  • 27
  • 136
  • 235
  • I would recommend Rhino Mocks - it is mature and powerful tool. About your problem - How do you test your queue objects for equality? – NOtherDev Oct 29 '10 at 09:20
  • I don't -- I just assumed that's what System.Collections.Generic.Queue.Contains() is doing. :) (But on further examination it may not be.) When I get around to writing the actual implementation of ISomeInterface I'll include making sure that Contains() works on it. – David Moles Oct 29 '10 at 17:19
  • +1 for trying Moq! It's my isolation framework of choice. – TrueWill Oct 29 '10 at 17:36

2 Answers2

0

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
  • 2,552
  • 1
  • 21
  • 33
  • `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. – NOtherDev Oct 29 '10 at 12:14
  • 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 Oct 29 '10 at 12:35
  • `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 Oct 29 '10 at 17:22
  • @David now your approach makes sense to me. – Jonny Cundall Oct 29 '10 at 18:22
0

Answering myself in order to close -- the answer seems to be "use Moq."

David Moles
  • 48,006
  • 27
  • 136
  • 235