544

How do I verify that method was NOT called in Moq?

Does it have something like AssertWasNotCalled?

UPDATE: Starting from Version 3.0, a new syntax can be used:

mock.Verify(foo => foo.Execute("ping"), Times.Never());
John Saunders
  • 160,644
  • 26
  • 247
  • 397
alex
  • 74,215
  • 9
  • 49
  • 57
  • As of v4.8, there's an [alternative approach](https://stackoverflow.com/a/71012880/5405967) that's also worth considering. – MarredCheese Feb 07 '22 at 03:00

8 Answers8

644

Run a verify after the test with the Times.Never() option.

_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(), Times.Never());
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Dan
  • 12,808
  • 7
  • 45
  • 54
  • 10
    What's critical here is that the Verify(action, Never) call is *after* the invocation to the mock. I thought it was setting up the verification for calling VerifyAll() later (which *does not* work) – piers7 Sep 04 '14 at 08:15
  • Not sure if it's because a newer version, but if you setup the mock with ´MockBehavior.Strict´ and don't add a Setup then it'll fail if the method is called. No need for a Verify. – Paw Baltzersen Oct 07 '20 at 10:04
169

UPDATE: Since version 3, check the update to the question above or Dann's answer below.

Either, make your mock strict so it will fail if you call a method for which you don't have an expect

new Mock<IMoq>(MockBehavior.Strict)

Or, if you want your mock to be loose, use the .Throws( Exception )

var m = new Mock<IMoq>(MockBehavior.Loose);
m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
Dan Fish
  • 2,372
  • 1
  • 14
  • 8
  • 9
    ... or Callback() to set some flag that can be asserted. – alex Feb 11 '09 at 16:27
  • 2
    Also with option#2, you can't have a VerifyAll in a general Teardown method - it will fail saying that the expectation was not met ; when the test should ideally pass. – Gishu Sep 30 '09 at 10:29
  • 61
    This isn't really a "verify not called" as it could be caught within the method and would still work - providing a false positive! – Dan Aug 20 '10 at 09:59
  • 5
    Expect is now deprecated – Tomasz Sikora Jul 30 '13 at 11:09
  • 1
    Even though this method is now obsolete, if you add version information, it can still be useful. – Matthijs Wessels Oct 08 '14 at 10:01
  • 1
    @alex' solution explicitly, using `Setup` instead of `Expect` looks like this: `mock.Setup(foo => foo.Execute("ping")).Callback(() => { flagWasExecutePingCalled = true; });`. If desired, the delegate in `Callback` can also be written `.Callback(() => flagWasExecutePingCalled = true)`. – Jeppe Stig Nielsen Feb 18 '15 at 09:03
  • 5
    This might have been the best possible way in 2009, but certainly not now. sorry – Fabio Milheiro Jul 22 '15 at 18:05
56

Stolen from: John Foster's answer to the question, "Need help to understand Moq better"

One of the things that you might want to test is that the pay method does not get called when a person aged over 65 is passed into the method

[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);
}
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
12

This does not work in recent versions of Moq (since at least 3.1), it should be specified in the Verify method as mentioned in the answer.

Actually, it's better to specify .AtMost(0) after the Returns statement.

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

Although the "throws" also works, AtMost(0) is more expressive IMHO.

Liam
  • 27,717
  • 28
  • 128
  • 190
miha
  • 3,287
  • 3
  • 29
  • 44
4

Using VerifyNoOtherCalls (requires Moq 4.8 or later)

This answer is an indirect approach. Instead of checking that a particular method wasn't called, you check that no unexpected calls were made in general.

Consider that a thorough test of a mock does 2 things:

  1. Verify that all expected calls were made
  2. Verify that no unexpected calls were made

If you're already doing step 1, adding step 2 is trivial:

// Step 1 (if relevant - see note below)
mock.Verify(..., Times.Exactly(2));
mock.Verify(..., Times.Once());
// ...

// Step 2
mock.VerifyNoOtherCalls();

Notes

  • If you omit step 1, step 2 will simply ensure no calls were made to the mock at all.
  • This does not require a strict mock.
  • Source: Moq Quickstart
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
1

I realise this is a very old question, but it just appeared in my sidebar, and I'd like to add my solution.

Many unit tests appear to mock several functions, as part of the setup, but then aren't used during the test.

Surely it's better to enable strict mocking (which means anything not explicitly setup will throw an exception), and then don't set up any functions you don't expect to be called. Or to put it another way, only set up the functions that one test expects to be called, and anything else will thrown an exception.

var thingBeingTested = new Mock<IThink>(MockBehaviour.Strict);

thingBeingTested.ThisWillThrowAnExceptionBecauseItHasNotBeenMocked();
Neil
  • 11,059
  • 3
  • 31
  • 56
  • See Chris's answer below, but one reason for an explicit negative test, it to make the design more explicit wrt to refactoring e.g. it might have consequences if a call is made – Paul Hatcher Oct 21 '22 at 07:00
0

Suppose you have this method and you want to test that it's not being called

//Setup    
var databaseSessionMock = new Mock<IDatabaseSession>();
databaseSessionMock.Setup(m => m.Commit()).Returns(true).Verifiable();
RepositoryFactory.Configure<IDatabaseSession>(databaseSessionMock.Object);

you can test like this

databaseSessionMock.Verify(m => m.Commit(It.IsAny()), Times.Never(), "Database Session mock object was not used");
Zia Qammar
  • 174
  • 12
-6

Use .AtMostOnce();

After the real test, call the method again. If it throws an exception, it was called.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820