Como verificar se o método NÃO foi chamado no Moq?

466

Como verifico que o método NÃO foi chamado no Moq ?

Tem algo como AssertWasNotCalled?

ATUALIZAÇÃO: A partir da versão 3.0, uma nova sintaxe pode ser usada:

mock.Verify(foo => foo.Execute("ping"), Times.Never());
alex
fonte

Respostas:

155

ATUALIZAÇÃO : Desde a versão 3, verifique a atualização da pergunta acima ou a resposta de Dann abaixo.

Ou, faça com que o seu mock seja estrito, para que ele falhe se você chamar um método para o qual você não espera

new Mock<IMoq>(MockBehavior.Strict)

Ou, se você quiser que seu mock seja solto, use o .Throws (Exception)

var m = new Mock<IMoq>(MockBehavior.Loose);
m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
Dan Fish
fonte
9
... ou Callback () para definir algum sinalizador que possa ser afirmado.
alex
2
Também com a opção 2, você não pode ter um VerifyAll em um método geral de desmontagem - falhará dizendo que a expectativa não foi atendida; quando o teste deve passar idealmente.
Gishu 30/09/09
51
Este não é realmente um "verificar não chamado", pois poderia ser detectado dentro do método e ainda funcionaria - fornecendo um falso positivo!
Dan
4
Agora, a expectativa foi preterida
Tomasz Sikora
5
Essa pode ter sido a melhor maneira possível em 2009, mas certamente não agora. desculpe
Fabio Milheiro
537

Execute uma verificação após o teste com um Times.Neverconjunto de enumerações. por exemplo

_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(),Times.Never());
Dan
fonte
4
O que é crítico aqui é que a chamada Verificar (ação, Nunca) é após a chamada para a simulação. Eu pensei que estava montando a verificação para chamar VerifyAll () mais tarde (que não trabalho)
piers7
Simples e eficaz. Obrigado.
21818 Ian Grainger
45

Roubado de: John Foster respondeu à pergunta "Precisa de ajuda para entender melhor o Moq"

Uma das coisas que você pode querer testar é que o método de pagamento não é chamado quando uma pessoa com mais de 65 anos passa para o método

[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {

    var mockPensionService = new Mock<IPensionService>();

    var person = new Person("test", 66);

    var calc = new PensionCalculator(mockPensionService.Object);

    calc.PayPensionContribution(person);

    mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}
Chris Marisic
fonte
10

Isso não funciona nas versões recentes do Moq (desde pelo menos 3,1), ele deve ser especificado no Verifymétodo conforme mencionado na resposta.

Na verdade, é melhor especificar .AtMost(0)após a instrução Returns.

var m = new Mock<ISomething>();
m.Expect(x => x.Forbidden()).Returns("foo").AtMost(0);

Embora os "lances" também funcionem, AtMost(0)é IMHO mais expressivo.

miha
fonte
-5

Use .AtMostOnce ();

Após o teste real, chame o método novamente. Se lançar uma exceção, foi chamado.

Aaron Digulla
fonte
1
Não é um pouco obscuro afirmar que a exceção foi lançada pela estrutura de zombaria?
alex
Por quê? Basta verificar o tipo da exceção. Se alguém jogou meu Moq, você está seguro.
23414 Aaron Digulla
8
Usando Verify com Times.Never é uma escolha melhor ... Concordo com alex que esta solução funciona, mas é definitivamente obscura.
Beep beep