Перевірте виклик методу за допомогою Moq


142

Я досить нова в одиничному тестуванні на C # і вчаться використовувати Moq. Нижче наведено клас, який я намагаюся перевірити.

class MyClass
{
    SomeClass someClass;
    public MyClass(SomeClass someClass)
    {
        this.someClass = someClass;     
    }

    public void MyMethod(string method)
    {
        method = "test"
        someClass.DoSomething(method);
    }   
}

class Someclass
{
    public DoSomething(string method)
    {
        // do something...
    }
}

Нижче знаходиться мій TestClass:

class MyClassTest
{
    [TestMethod()]
    public void MyMethodTest()
    {
        string action="test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
        mockSomeClass.SetUp(a => a.DoSomething(action));
        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);
        mockSomeClass.Verify(v => v.DoSomething(It.IsAny<string>()));
    }
}

Я отримую таке виняток:

Expected invocation on the mock at least once, but was never performed
No setups configured.
No invocations performed..

Я просто хочу перевірити, викликається чи ні метод "MyMethod". Я щось пропускаю?


1
Це не буде компілюватися, якщо у SomeClassнього немає визначення для MyMethod(string)якого, схоже, це не так.
Platinum Azure

вибачте .. Я відредагував своє запитання ..
user591410

1
Ви на правильному шляху, але у розміщеному коді є помилки. Він не буде компілюватися - обробка на Someclass, недійсна віддача на DoSomething. Після цього вам потрібен загальнодоступний доступ, а потім зробіть DoSomething віртуальним. Коротше кажучи, у вас, ймовірно, є помилка і у виробничому коді.
TrueWill

Дякую за Вашу відповідь. Я встановлював аргументи неправильно під час налаштування методу макету ..
user591410

"Налаштування не налаштовано." Може ввести в оману. Вам не потрібно налаштовувати поведінку на методи, які будуть викликатися. А також не забудьте виконати метод "Перевірити" ПІСЛЯ методу, який ви тестуєте, слід викликати (так що у вашому випадку це нормально).
Сіелу

Відповіді:


209

Ви перевіряєте неправильний метод. Moq вимагає, щоб ви встановили (а потім необов'язково підтвердили) метод у класі залежності.

Вам слід робити щось подібне:

class MyClassTest
{
    [TestMethod]
    public void MyMethodTest()
    {
        string action = "test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();

        mockSomeClass.Setup(mock => mock.DoSomething());

        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);

        // Explicitly verify each expectation...
        mockSomeClass.Verify(mock => mock.DoSomething(), Times.Once());

        // ...or verify everything.
        // mockSomeClass.VerifyAll();
    }
}

Іншими словами, ви перевіряєте, що виклик MyClass#MyMethod, ваш клас обов'язково зателефонує SomeClass#DoSomethingодин раз у цьому процесі. Зауважте, що Timesаргумент вам не потрібен ; Я просто демонстрував її цінність.


Вибачте, я змінив своє запитання правильним методом. Як ви вже згадували, спершу я спробував SetUp, а потім виконав Verify. Це все ще дає мені той самий виняток.
користувач591410

22
Чи не зайвим є налаштування очікування, а потім чітко підтвердити те саме очікування? Не вдалося б mockSomeClass.VerifyAll();досягти такого ж результату і бути більш СУХОЮ?
Тім Лонг

14
Так, але, але деякі люди вважають за краще явне.
Platinum Azure

3
Дякуємо, що принаймні згадуєте VerifyAll (); в той час як очевидно, коли ви думаєте про це. Я, можливо, пішов на явний підхід, але набагато чистіший при використанні всіх. Вдячні обидва перераховані.
JGood

1
Один з пов'язаних недоліків Mockпорівняно з NSubstituteтим, що якщо ви намагаєтеся перевірити також параметри та не вдалося підтвердити, він просто показує, які виклики були виконані, але не показує, що саме очікувалося, якщо ви використовували змінні в виразі перевірки - він просто показуватиме змінну ім'я, а не його значення, тому вам доведеться налагоджувати, щоб перевірити, яке саме значення має ця змінна. NSubstitute буде просто показувати значення як і навіть там, де це було інше.
Гренгас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.