Sprawdź wywołanie metody przy użyciu Moq

142

Jestem całkiem nowy w testowaniu jednostkowym w C # i uczę się używać Moq. Poniżej znajduje się klasa, którą próbuję przetestować.

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...
    }
}

Poniżej znajduje się moja klasa 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>()));
    }
}

Otrzymuję następujący wyjątek:

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

Chcę tylko sprawdzić, czy metoda „MyMethod” jest wywoływana, czy nie. Czy coś mi brakuje?

user591410
źródło
1
To się nie skompiluje, jeśli SomeClassnie ma definicji, dla MyMethod(string)której wygląda na to, że jej nie ma.
Platinum Azure,
przepraszam .. zredagowałem moje pytanie ..
user591410
1
Jesteś na dobrej drodze, ale w opublikowanym kodzie są błędy. Nie skompiluje się - obudowa w Someclass, void return w DoSomething. Następnie potrzebujesz publicznego dostępu, a następnie utwórz wirtualną funkcję DoSomething. Krótko mówiąc, prawdopodobnie masz również błąd w kodzie produkcyjnym.
TrueWill
Dzięki za twoją odpowiedź. Podczas konfigurowania metody
próbnej ustawiłem
„Brak skonfigurowanych ustawień”. Może być mylące. Nie musisz konfigurować zachowania dla metod, które zostaną wywołane. Pamiętaj też, aby wykonać metodę "Verify" PO wywołaniu metody, którą testujesz (więc w twoim przypadku jest to w porządku).
Sielu

Odpowiedzi:

209

Sprawdzasz niewłaściwą metodę. Moq wymaga skonfigurowania (a następnie opcjonalnie weryfikacji) metody w klasie zależności.

Powinieneś zrobić coś bardziej podobnego:

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();
    }
}

Innymi słowy, weryfikujesz to połączenie MyClass#MyMethod, twoja klasa na pewno zadzwoni SomeClass#DoSomethingraz w tym procesie. Zauważ, że nie potrzebujesz Timesargumentu; Właśnie pokazywałem jego wartość.

Platinum Azure
źródło
Przepraszam, zredagowałem moje pytanie właściwą metodą. Jak wspomniałeś, najpierw wypróbowałem SetUp, a następnie przeprowadziłem weryfikację. Nadal daje mi ten sam wyjątek.
user591410
22
Czy nie jest zbędne konfigurowanie oczekiwania, a następnie jawne weryfikowanie tego samego oczekiwania? Czy nie mockSomeClass.VerifyAll();osiągnąłby tego samego rezultatu i nie byłby bardziej SUCHY?
Tim Long
14
Tak, ale niektórzy wolą mówić wprost.
Platinum Azure
3
Dziękuję za wspomnienie o VerifyAll (); choć oczywiste, kiedy się nad tym zastanowić. Mógłbym wybrać wyraźne podejście, ale znacznie czystsze, gdy używam all. Wdzięczne oba są wymienione.
JGood
1
Jedną z powiązanych wad w Mockporównaniu do NSubstitutejest to, że jeśli próbujesz zweryfikować również parametry i weryfikacja się nie powiedzie, pokazuje tylko, jakie wywołania zostały wykonane, ale nie pokazuje, czego dokładnie oczekiwano, jeśli użyłeś zmiennych w wyrażeniu weryfikacyjnym - pokaże tylko zmienną nazwa, a nie wartość, więc będziesz musiał debugować, aby sprawdzić, jaką dokładnie wartość ma ta zmienna. NSubstitute po prostu pokaże wartości obu, a nawet tam, gdzie było inaczej.
Grengas