Reputation: 75945
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());
Upvotes: 559
Views: 123912
Reputation: 20811
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:
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
Upvotes: 8
Reputation: 13343
Run a verify after the test with the Times.Never()
option.
_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(), Times.Never());
Upvotes: 663
Reputation: 11889
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();
Upvotes: 2
Reputation: 194
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");
Upvotes: 0
Reputation: 33098
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); }
Upvotes: 57
Reputation: 3377
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.
Upvotes: 12
Reputation: 2392
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."));
Upvotes: 171
Reputation: 328594
Use .AtMostOnce();
After the real test, call the method again. If it throws an exception, it was called.
Upvotes: -6