Comment vérifier qu'une autre méthode de la classe a été appelée avec Moq

StackOverflow https://stackoverflow.com/questions/1417048

  •  06-07-2019
  •  | 
  •  

Question

Cela semble être quelque chose de simple mais je n'arrive pas à le faire fonctionner.

J'ai une classe avec une méthode Save qui appelle simplement une autre méthode ShouldBeCalled (). Je veux vérifier que si j'appelle Save (), l'autre méthode ShouldBeCalled () est exécutée au moins une fois. Je pensais pouvoir faire ce qui suit.

public class ClassA
{
    public virtual void Save()
    {
        ShouldBeCalled();
    }

    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        var mockClassA = new Mock<ClassA>();
        mockClassA.Object.Save();

        mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
    }
}

Mais je reçois l'exception " L'invocation attendue sur la maquette au moins une fois, mais n'a jamais été exécutée: x = > x.ShouldBeCalled () "

C'est une supposition, mais Moq redéfinit-il la méthode Save () avec sa propre version, qui ignore tout ce que j'ai à l'intérieur de la méthode Save () de l'objet réel.

Était-ce utile?

La solution

Vous rencontrez ce problème parce que vous vous moquez de ce que vous testez. Cela n’a aucun sens.

Vous avez raison de dire que Moq va remplacer la mise en oeuvre de votre méthode par la sienne. La raison en est que vous êtes censé utiliser Moq pour simuler des choses de la classe que vous testez , pas de la classe que vous testez elle-même.

Ce test serait approprié si votre code était conçu de la manière suivante:

public class ClassA
{
    BusinessLogicClass bl;
    public ClassA(BusinessLogicClass bl)
    {
         this.bl = bl;
    }

    public void Save()
    {
        bl.ShouldBeCalled();
    }
}

public class BusinessLogicClass
{
    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

Et voici le test correct de cette méthode maintenant:

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_ShouldCallShouldBeCalled()
    {
        //Arrange
        var mockBLClass = new Mock<BusinessLogicClass>();
        mockBLClass.Setup(x => x.ShouldBeCalled()).Verifyable();

        //Act    
        ClassA classA = new ClassA(mockBLClass.Object);
        classA.Save();

        //Assert
        mockBLClass.VerifyAll();
    }
}

La principale leçon à retenir ici est que vous simulez / stubez ce que votre test doit exécuter , et non ce que vous testez lui-même.

J'espère que ça aide, Anderson

Autres conseils

Essayez d’utiliser CallBase = true, puis false. J'ai couru votre code et ça marche.

var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true;
mockClassA.Object.Save();
mockClassA.CallBase = false;
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());

Oui, cela peut être fait. Cependant, vous devez ajouter une ligne de code pour permettre à Moq de savoir si la méthode ShouldBeCalled a bien été appelée.

Quelque chose comme ce qui suit fonctionnera:

var mockClassA = new Mock<ClassA>();
mockClassA.Setup(x => x.ShouldBeCalled()).Verifiable();    
mockClassA.Object.Save();    
mockClassA.Verify(x => s.ShouldBeCalled(), Times.AtLeastOnce());

La méthode de configuration définit les attentes. Lorsque vous appelez Verify, vous demandez à Moq de vérifier ces attentes. Si vous ne lancez pas d'appel de la configuration pour créer des attentes pour la méthode ShouldBeCalled, Moq ne considère pas qu'elle soit traçable et échouera dès lors lorsque vous essayez de la vérifier.

Vous pouvez remplacer les méthodes du système testé par CallBase .

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        // Arrange
        var mockClassA = new Mock<ClassA>();
        mockClassA.CallBase = true; // this will call real methods unless the method is mocked/stubbed. 
        mockClassA.Setup(a => a.ShouldBeCalled());

        // Act
        mockClassA.Save();

        // Assert
        mockClassA.Verify(a => a.ShouldBeCalled(), Times.Once());
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top