Правильный способ проверить это с moq - PullRequest
1 голос
/ 12 января 2012

Я написал реализацию для нужной мне приоритетной очереди, и теперь я хотел бы протестировать ее. Я решил использовать moq, так как я уже использовал moh rhino на работе и хочу попробовать что-то новое / возможно, более простое.

Интерфейс для моего 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 });
    }
}

Первый модульный тест, который я написал, состоял в том, чтобы проверить, был ли ключ пустым, он должен выдавать исключение аргумента пустое.

[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 никогда не будет вызываться, потому что я создаю экземпляр экземпляра моего интерфейса, а не реализацию. Тогда возникает вопрос, а если я должен протестировать с использованием своих интерфейсов (по крайней мере, такое впечатление я получил после просмотра TDD - Понимание Mock Objects Роя Ошерова), как мне это сделать? проверить мою реализацию?

Неужели я не правильно понял совет по тестированию интерфейсов?

В видео он создал класс в тесте, который он писал, и использовал его для тестирования. Я не понимаю, как это помогло бы мне проверить мою реализацию PriorityQueue (в частности, метод Enqueue).

Спасибо, переполнение стека!

edit: Вот следующий (безобразный) рабочий тест, который я придумал. Я крайне недоволен этим, это кажется таким примитивным. Кто-нибудь может предложить лучший способ сделать это? Из приведенных ниже ответов кажется, что для этого модульного теста рамки совершенно не нужны.

Однако вот оно:

[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);   
}

Ответы [ 3 ]

4 голосов
/ 12 января 2012

Я думаю, что есть некоторое недоразумение.

Если у вашего тестового объекта есть зависимости, которые определены как интерфейсы, вы должны смоделировать их, чтобы иметь возможность протестировать ваш модуль.

В вашем случае у вас нет зависимостей, которые нужно заменить для тестирования. Поскольку вы хотели бы протестировать вашу реализацию, нет смысла ее высмеивать. ИМХО нет необходимости тестировать существующий класс 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);
}
2 голосов
/ 12 января 2012

Вы ошибаетесь.Вам не нужно макет IPriorityQueue, когда вы тестируете методы одной из его реализаций.То, что вам нужно, это макет queue

Обязанности метода Enqueue:

  1. , выбрасывающее исключение, если приоритет равен нулю
  2. , выполняющее что-то при условии
  3. выполнение чего-либо в другом условии

Для тестирования # 1 достаточно просто, и реализации заглушки queue будет достаточно, для # 2 и # 3 вам понадобится макетqueue.Для # 2 и # 3 вы должны проверить, вызваны ли методы Add фиктивной очереди с правильными параметрами

1 голос
/ 11 апреля 2012

Вместо этого можно использовать атрибут [ExceptionExpected].

[TestMethod]
[ExpectedException(ExpectedException = typeof(ArgumentNullException)]
public void EnqueueNullKey_ThrowsArgumentNullException()
{
    /* Arrange */
    var pq = new PriorityQueue<string, IMessage>();

    /* Act */
    pq.Enqueue(null, null);
}

Тест не пройден, если ArgumentNullException не выброшено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...