Moq gebruiken om te bepalen of een methode wordt aangeroepen

Ik heb begrepen dat ik kan testen of een methodeaanroep zal plaatsvinden als ik een methode van een hoger niveau aanroep, d.w.z.:

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

Ik wil testen dat als ik SomeMethod()aanroep, ik verwacht dat SomeOtherMethod()zal worden aangeroepen.

Heb ik gelijk als ik denk dat dit soort tests beschikbaar is in een spottend kader?


Antwoord 1, autoriteit 100%

Je kunt zien of een methode in iets dat je hebt bespot, is aangeroepen door Verify te gebruiken, bijvoorbeeld:

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

Als de regel als commentaar wordt achtergelaten, wordt er een MockException gegenereerd wanneer u Verify aanroept. Als er geen commentaar op wordt gegeven, gaat het over.


Antwoord 2, autoriteit 3%

Nee, bij schijntesten wordt ervan uitgegaan dat u bepaalde testbare ontwerppatronen gebruikt, waaronder injectie. In jouw geval zou je SomeClass.SomeMethodtesten en SomeOtherMethodmoet worden geïmplementeerd in een andere entiteit die moet worden gekoppeld.

Uw SomeClass-constructor ziet eruit als New(ISomeOtherClass). Dan zou je de ISomeOtherClassbespotten en de verwachting instellen op zijn SomeOtherMethodom te worden aangeroepen en de verwachting te verifiëren.


Antwoord 3

Hoewel ik het ermee eens ben dat het @Paul’s antwoordde aanbevolen manier is, wil ik slechts één alternatieve manier toevoegen die wordt geleverd door moqvan zichzelf.

Aangezien SomeClassabstractis, is het inderdaad bespottelijk, maar public void SomeMehod()is dat niet. Het gaat erom de manier te vinden om die methode te bespotten en op de een of andere manier aan te roepen en vervolgens CallBasete gebruiken om de aanroep door te geven aan de SomeOtherMethod(). Het klinkt misschien als een hack, maar het is in wezen eenvoudig. Het kan worden gebruikt in het geval dat de voorgestelde refactoring niet mogelijk is.

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

Vervolgens zou je DummyMethod()kunnen instellen om de aanroep te verspreiden door de vlag CallBasein te stellen.

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();
//Act
mock.Object.SomeMethod();
//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

Other episodes