Reputation: 7837
I wrote an implementation for a priority queue I needed, and now I would like to test it. I decided on using moq, as I've already used rhino mocks at work and want to try something new/possibly easier.
The interface for my PriorityQueue is pretty straight-forward:
public interface IPriorityQueue<TKey, TValue> where TKey : IComparable
{
void Enqueue(TKey priority, TValue value);
bool IsEmpty();
TValue Peek();
TValue Dequeue();
}
I went to write my first test, which tests the Enqueue method. Here's the implementation for it:
public void Enqueue(TKey priority, TValue value)
{
if (priority == null) { throw new ArgumentNullException("priority"); }
if (_queue.ContainsKey(priority))
{
// queue contains key, therefore just add value to existing key's list
_queue[priority].Add(value);
}
// otherwise just add pair
else
{
_queue.Add(priority, new List<TValue>() { value });
}
}
The first unit test I wrote was to test if the key was null, it should throw an argument null exception.
[TestMethod]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
/* Arrange */
var mock = new Mock<IPriorityQueue<string, IMessage>>();
// string implements the IComparable interface, and is nullable.
mock
.Setup(x => x.Enqueue(null, It.IsAny<IMessage>()))
.Throws<ArgumentNullException>();
/* Assert */
mock.VerifyAll();
}
So I realize now, that my method Enqueue will never be called, because I am instantiating an instance of my interface, not the implementation. Then the question begs to be asked, if I'm supposed to test with using my interfaces (at-least that was the impression I got after watching Roy Osherove's TDD - Understanding Mock Objects video) how am I to test my implementation?
Am I misunderstanding the advice to test with interfaces?
In the video he created a class within the test he was writing, and used that to test. I don't see how that would help me test my implementation of PriorityQueue (specifically the Enqueue method).
Thanks stack overflow!
edit: Here's the following (ugly) working test that I've came up with. I'm extremely unhappy with it, it feels so primitive. Can anyone suggest a better way of doing this? From the responses below, it seems like the framework is completely unnecessary for this unit test.
However, here it is:
[TestMethod]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
/* Arrange */
var pq = new PriorityQueue<string, IMessage>();
try
{
pq.Enqueue(null, null);
}
catch(ArgumentNullException)
{
Assert.IsTrue(true);
return;
}
// failure condition if we don't catch the exception
Assert.IsTrue(false);
}
Upvotes: 1
Views: 1428
Reputation: 1266
You could use the [ExceptionExpected]
attribute instead.
[TestMethod]
[ExpectedException(ExpectedException = typeof(ArgumentNullException)]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
/* Arrange */
var pq = new PriorityQueue<string, IMessage>();
/* Act */
pq.Enqueue(null, null);
}
The test will fail if the ArgumentNullException
is not thrown.
Upvotes: 1
Reputation: 10344
I think there is some misunderstanding.
If your test object has dependencies, which are defined as interfaces, you would mock these in order to be able to test your unit.
In your case, you have no dependencies which you need to replace for testing. As you would like to test your implementation, there is no sense to mock it. IMHO it is not necessary to test an existing class of the BCL.
A test (Nunit) test could look like this (untested)
[TestMethod]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
var queue = new YourPriorityQueue<string, IMessage>();
var message = new SomeFooMessage(); // or use a mock for this
Assert.Throws(typeof(ArgumentNullException), () => queue.Enqueue(null, message);
}
Upvotes: 4
Reputation: 19117
You are getting it wrong. You don't need a mock of IPriorityQueue
when you are testing methods on one of its implementation. What you need is a mock of queue
The responsibilities of Enqueue
method are
For #1 testing is quite easy and a stub implementation of queue
will suffice, for #2 and #3 you will need a mock of queue
. For #2 and #3 you should test if mock queue's Add methods is called with correct parameters
Upvotes: 2