我为我需要的优先级队列编写了一个实现,现在我想测试它。我决定使用moq,因为我已经在工作中使用过犀牛嘲讽,并想尝试一些新的/可能更容易的东西。
我的PriorityQueue界面非常简单:
public interface IPriorityQueue<TKey, TValue> where TKey : IComparable
{
void Enqueue(TKey priority, TValue value);
bool IsEmpty();
TValue Peek();
TValue Dequeue();
}
我去写了我的第一个测试,它测试了Enqueue方法。以下是它的实现:
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 });
}
}
我写的第一个单元测试是测试密钥是否为null,它应该抛出一个参数null异常。
[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();
}
所以我现在意识到,我的方法Enqueue永远不会被调用,因为我实例化了我的接口实例,而不是实现。然后问题就是要问,如果我应该使用我的界面进行测试(至少这是我在观看Roy Osherove的TDD - Understanding Mock Objects视频后得到的印象)我如何测试我的实现?
我是否误解了使用接口进行测试的建议?
在视频中,他在他正在编写的测试中创建了一个类,并用它进行测试。我不知道这将如何帮助我测试我的PriorityQueue(特别是Enqueue方法)的实现。
感谢堆栈溢出!
编辑:这是我提出的以下(丑陋)工作测试。我对它非常不满意,感觉很原始。谁能建议更好的方法呢?从下面的回答来看,这个单元测试似乎完全没有框架。
但是,这是:
[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);
}
答案 0 :(得分:4)
我认为存在一些误解。
如果您的测试对象具有依赖项(定义为接口),您可以模拟它们以便能够测试您的单元。
在您的情况下,您没有需要替换以进行测试的依赖项。由于您希望测试您的实现,因此无需模拟它。恕我直言,没有必要测试现有的BCL类。
测试(Nunit)测试看起来像这样(未经测试)
[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);
}
答案 1 :(得分:2)
你弄错了。当您在其中一个实现上测试方法时,您不需要模拟IPriorityQueue
。你需要的是模拟queue
Enqueue
方法的职责是
对于#1测试非常简单,queue
的存根实现就足够了,对于#2和#3,你需要模拟queue
。对于#2和#3,您应该测试是否使用正确的参数调用模拟队列的Add方法
答案 2 :(得分:1)
您可以使用[ExceptionExpected]
属性。
[TestMethod]
[ExpectedException(ExpectedException = typeof(ArgumentNullException)]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
/* Arrange */
var pq = new PriorityQueue<string, IMessage>();
/* Act */
pq.Enqueue(null, null);
}
如果未抛出ArgumentNullException
,测试将失败。