Usando o Moq para determinar se um método é chamado


159

Entendo que posso testar se uma chamada de método ocorrerá se eu chamar um método de nível superior, ou seja:

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

    internal abstract void SomeOtherMethod();
}

Quero testar se, se eu ligar SomeMethod(), espero que SomeOtherMethod()isso seja chamado.

Estou certo ao pensar que esse tipo de teste está disponível em uma estrutura de simulação?

Respostas:


186

Você pode ver se um método em algo que você zombou foi chamado usando o Verify, por exemplo:

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

Se a linha for deixada comentada, lançará uma MockException quando você chamar Verify. Se não estiver comentado, passará.


7
Essa é a resposta correta. Você deve entender alguma coisa, no entanto. Você NÃO PODE zombar de um método / propriedade que não seja abstrato ou virtual (obviamente, todos os métodos e propriedades da interface podem ser zombados).

25
-1: O .Expect (...). Verificável () é redundante neste código. Usando AAA, verifique se você está certo. .Verificiable é para uso com .Verify () i, .e. a versão sem argumento. Veja stackoverflow.com/questions/980554/…
Ruben Bartelink

@ Eu- sim pode
reggaeguitar

6

Não, o teste simulado pressupõe que você esteja usando determinados padrões de design testáveis, um dos quais é a injeção. No seu caso, você estaria testando SomeClass.SomeMethod e SomeOtherMethoddeve ser implementado em outra entidade que precisa ser conectada.

O seu Someclassconstrutor seria semelhante New(ISomeOtherClass). Em seguida, você zombaria ISomeOtherClasse definiria a expectativa SomeOtherMethodde ser chamado e verificaria a expectativa.


0

Embora eu concorde que a resposta do @ Paul é o caminho recomendado, eu só quero adicionar um caminho alternativo que é fornecido por você moqmesmo.

Desde SomeClassé abstractque é realmente mockable, mas public void SomeMehod()não é. O objetivo é encontrar a maneira de zombar e de alguma forma invocar esse método e, em seguida, usar a CallBasepropagação da chamada para o SomeOtherMethod(). Pode parecer um hack, mas é simples em essência. Pode ser usado no caso se a refatoração proposta não for possível.

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

Em seguida, você pode configurar DummyMethod()para propagar a chamada definindo CallBasesinalizador.

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

Downvoted porque é mais complicado e requer um clichê DummyClass
reggaeguitar

upvoted porque às vezes você não pode refatorar e você precisa testar a implementação, tal como está
wickdninja
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.