Используя Moq, чтобы определить, вызван ли метод

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

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

    internal abstract void SomeOtherMethod();
}

Я хочу проверить, что если я вызову SomeMethod(), то я ожидаю, что будет вызван SomeOtherMethod().

Я правильно понял, что такой тест доступен в насмешливой структуре?

Ответ 1

Вы можете увидеть, вызван ли метод в том, что вы издевались, с помощью 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 при вызове Verify. Если он раскоментирован, он пройдет.

Ответ 2

Нет, макет тестирования предполагает, что вы используете определенные тестируемые шаблоны проектирования, одним из которых является инъекция. В вашем случае вы будете тестировать SomeClass.SomeMethod и SomeOtherMethod должны быть реализованы в другом объекте, который должен быть сопряжен.

Конструктор Someclass будет выглядеть как New(ISomeOtherClass). Затем вы издеваетесь над ISomeOtherClass и задаете ожидание на своем SomeOtherMethod для вызова и проверки ожидания.

Ответ 3

Несмотря на то, что я согласен, что ответ @Paul - рекомендуемый путь, я просто хочу добавить один альтернативный путь, который обеспечивает moq off the self.

Так как SomeClass является abstract это действительно насмешливо, но public void SomeMehod() - нет. CallBase том, чтобы найти способ CallBase и каким-то образом вызвать этот метод, а затем с помощью 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);