Проверить вызов метода с помощью Moq

151

Я новичок в модульном тестировании на 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 или нет. Я что-то упускаю?

user591410
источник
1
Это не будет компилироваться, если SomeClassне будет определения, для MyMethod(string)которого, похоже, нет.
Platinum Azure
извините .. я отредактировал свой вопрос ..
user591410 03
1
Вы на правильном пути, но в опубликованном коде есть ошибки. Он не будет компилироваться - оболочка Someclass, возврат void на DoSomething. После этого вам понадобится публичный доступ, а затем сделайте DoSomething виртуальным. Короче говоря, у вас, вероятно, тоже есть ошибка в производственном коде.
TrueWill
Спасибо за ваш ответ. Я неправильно
указывал
«Никаких настроек не настроено». Может ввести в заблуждение. Вам не нужно настраивать поведение для методов, которые будут вызываться. А также не забудьте выполнить метод «Verify» ПОСЛЕ того, как должен быть вызван метод, который вы тестируете (так что в вашем случае это нормально).
Сиелу

Ответы:

218

Вы проверяете неправильный метод. 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. Это по-прежнему дает мне то же исключение.
user591410 03
23
Разве не избыточно устанавливать ожидание, а затем явно проверять это ожидание? Не могли бы mockSomeClass.VerifyAll();достичь того же результата и быть более СУХИМ?
Тим Лонг,
14
Да, но некоторые люди предпочитают быть откровенным.
Platinum Azure
3
Спасибо, что хотя бы упомянули VerifyAll (); Хотя это очевидно, если подумать. Я, возможно, выбрал явный подход, но при использовании all. Благодарны, оба перечислены.
JGood
1
Один связанный с этим недостаток по Mockсравнению с NSubstituteзаключается в том, что если вы пытаетесь проверить также параметры и проверка не выполняется, он просто показывает, какие вызовы были выполнены, но не показывает, что именно ожидалось, если вы использовали переменные в выражении проверки - он просто покажет переменную имя, а не его значение, поэтому вам нужно выполнить отладку, чтобы проверить, какое именно значение имеет эта переменная. NSubstitute просто покажет значения обоих, даже если они были разными.
Grengas