Використання Moq для визначення, чи викликається метод


159

Наскільки я розумію, я можу перевірити, що виклик методу відбудеться, якщо я викликаю метод вищого рівня, тобто:

public abstract class SomeClass()
{    
    public void SomeMehod()
    {
        SomeOtherMethod();
    }

    internal abstract void SomeOtherMethod();
}

Я хочу перевірити, що якщо я зателефоную, SomeMethod()то очікую, що SomeOtherMethod()він зателефонує.

Я маю рацію, думаючи, що такий тест доступний у глузливій структурі?

Відповіді:


186

Ви можете побачити, чи був викликаний метод у чомусь, що ви знущалися, за допомогою Verify, наприклад:

static void Main(string[] args)
{
        Mock<ITest> mock = new Mock<ITest>();

        ClassBeingTested testedClass = new ClassBeingTested();
        testedClass.WorkMethod(mock.Object);

        mock.Verify(m => m.MethodToCheckIfCalled());
}

class ClassBeingTested
{
    public void WorkMethod(ITest test)
    {
        //test.MethodToCheckIfCalled();
    }
}

public interface ITest
{
    void MethodToCheckIfCalled();
}

Якщо рядок залишено коментарем, він видасть MockException, коли ви зателефонуєте Перевірити. Якщо це буде прокоментовано, воно пройде.


7
Це правильна відповідь. Ти повинен щось зрозуміти. Ви НЕ МОЖЕТЕ висміювати метод / властивість, який не є абстрактним або віртуальним (очевидно, з усіх методів та властивостей інтерфейсу можна знущатися).

25
-1: .Epepect (...). Перевіряється () є зайвим у цьому коді. Використовуючи AAA, перевірка у вас є правильною. .Перевіряється для використання з .Verify () i, .e. версія без аргументів Див stackoverflow.com/questions/980554 / ...
Ruben Bartelink

@ I-- так, це може
reggaeguitar

6

Ні, макетне тестування передбачає, що ви використовуєте певні випробувані конструкції, однією з яких є ін'єкція. У вашому випадку ви проходите тестування SomeClass.SomeMethod і SomeOtherMethodповинні бути реалізовані в іншому об'єкті, яке потребує взаємодії.

Ваш Someclassконструктор виглядав би так New(ISomeOtherClass). Тоді ви б знущалися над ISomeOtherClassі задавали очікування на його SomeOtherMethodвиклик і перевіряли очікування.


0

Хоча я погоджуюся, що відповідь @ Павла - це рекомендований шлях, я просто хочу додати один альтернативний шлях, який забезпечується moqвиключенням самості.

Так як SomeClassце abstractце дійсно mockable, але public void SomeMehod()це не так . Сенс полягає в тому, щоб знайти спосіб знущатися і якось викликати цей метод, а потім за допомогою CallBaseрозповсюдження виклику до SomeOtherMethod(). Це може звучати як хак, але по суті це просто. Він може бути використаний у тому випадку, якщо запропонований рефакторинг неможливий.

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
    public virtual void DummyMethod() => base.SomeMethod();
}

Тоді ви можете налаштувати DummyMethod()розповсюдження дзвінка, встановивши CallBaseпрапор.

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

Запропонований тому, що він складніший і вимагає котловану DummyClass
reggaeguitar

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