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


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.