How to verify that method was NOT called in Moq? - c#

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

Run a verify after the test with the Times.Never() option.
_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(), Times.Never());

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."));

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

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.

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:
Verify that all expected calls were made
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

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

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");

Use .AtMostOnce();
After the real test, call the method again. If it throws an exception, it was called.

Related

What is the FakeItEasy equivalent of the Moq VerifyNoOtherCalls() method

I'm currently a Moq user and I'm researching other mocking frameworks.
When unit testing I frequently call _mock.VerifyNoOtherCalls() so I can be certain there are no unexpected interactions beyond the ones that I have already verified.
I've searched the FakeItEasy docs and cannot find the equivalent option in their framework. Can anyone suggest how I might do this?
Strict fakes
FakeItEasy supports strict fakes (similar to strict mocks in Moq):
var foo = A.Fake<IFoo>(x => x.Strict());
This will fail the moment an unexpected call is made.
Semi-strict fakes
It is also possible to configure all calls directly:
A.CallTo(fakeShop).Throws(new Exception());
and combine this with specifying different behaviors for successive calls, however in this case, there's no benefit to doing so over using a strict fake, as a strict fake will give better messages when unconfigured methods are called. So if you want to configure some methods to be called a limited number of times, you could
var fakeShop = A.Fake<IShop>(options => options.Strict());
A.CallTo(() => fakeShop.GetTopSellingCandy()).Returns(lollipop).Once();
A.CallTo(() => fakeShop.Address).Returns("123 Fake Street").Once();
fakeShop.GetTopSellingCandy() and fakeShop.Address can be called once, the second time it will fail.
Arbitrary checks
If you want to check if no calls are made at arbitrary points in the test:
A.CallTo(fakeShop).MustNotHaveHappened();
It might be better to filter out some of the methods that can be executed while debugging:
A.CallTo(a)
.Where(call => call.Method.Name != "ToString")
.MustNotHaveHappened();
You don't want a failing test because you hovered over the variable.

NSubstitute test works by itself, but throws Unexpected Matcher Argument in a suite

I have a unit test where I use .Returns() to return some sample data:
[TestMethod]
public void TestRetrieveElementsInVersion()
{
IRetrieveElementSequence component = Substitute.For<IRetrieveElementSequence>();
List<UnconstructedElement> list = new List<UnconstructedElement>
{
new UnconstructedElement{Version = "1"},
new UnconstructedElement{Version = "2"}
};
component.RetrieveElements().Returns(list); // exception reported here
const string target = "1";
IRetrieveElementSequence service = new RetrieveElementsInAVersion(component, target);
IList<UnconstructedElement> result = service.RetrieveElements();
bool check = result.All(e => e.Version == target);
Assert.IsTrue(check);
}
This code passes in Visual Studio using the ReSharper runner, when the test is run alone. It fails when it runs as part of a list, like when I Run All Tests from Solution.
NSubstitute.Exceptions.UnexpectedArgumentMatcherException: Argument matchers (Arg.Is, Arg.Any) should only be used in place of member arguments. Do not use in a Returns() statement or anywhere else outside of a member call.
I don't see where I am even using Arg.Any or Arg.Is. What am I doing that makes NSubstitute complain? This happens when I use the .Returns() to return lists of non-native objects.
This is most like due to a previous test using an argument matcher against a non-virtual method, or in a Returns statement.
Unfortunately this can be quite tricky to debug. First step is to see if the problem occurs when you run all the test in this fixture. If so, check all uses of Arg.Is|Any in that fixture, starting with the one that runs immediately before the test that fails (if your test framework uses a predictable test order, otherwise you'll need to look at test logs to see what tests proceed the failing one).
If it does not occur with that fixture you'll need to look through the fixtures that run beforehand to see where the left over arg matcher is coming from. It is most likely somewhere near the failing test.
EDIT 2021-03-28: The NSubstitute.Analyzers package can help to find these issues at compile time. I highly recommend adding it to any test project that includes NSubstitute.
In my case, it was a Received() call on exension method (likely because it's not virtual).
So I went back to my pull request and removed every instance of it and it worked.

How would you test it? How many tests?

I have this class (it's more pseudocode)
public class Roles
{
private ProcessData processData;
Roles(ProcessData pd)
{
processData = pd;
}
public string[] GetLoginsThatCanCallAction(string actionName)
{
return GetPeopleThatCanCallActionFromDb(actionName)
.Union(processData.ProcessOwner)
.Union(GetFromDb(Role.Administrators);
// there may be many more Union(xyz) calls here
.ToArray();
}
// I can refactor those methods to be mockable
private GetPeopleThatCanCallActionFromDb(...)
private GetFromDb(...)
}
Now my question is. Would you write one test for each Union call in GetLoginsThaatCanRunAction method?
Or is is just enough that I write one test and assert that method returns logins returned from all methods called inside GetLoginsThatCanCallAction.
I can see reasons to do it both ways. But maybe someone will convince me to on or the other solution.
Edit:
I think I wasn't clear with my question: I wanted to ask if you would write this test
var pd = new ProcessData()
pd.ProcessOwner = "Owner";
var r = new Roles(processData)
SetupSoThatCallsForPeopleThatCanCallActionWillReturn("Joe");
SetupSoThatCallForAdministratorsWillReturn("Administrator");
var logins = r.GetLoginsThatCanCallAction("some action");
Assert.That(logins, Contains("Owner");
Assert.That(logins, Contains("Joe");
Assert.That(logins, Contains("Administrator");
or would you split it into 3 separate tests with one Assert in each one?
Interesting topic, Your problem is that you are trying to write a test case after you have some code developed. I would have 1 test for each Union call. The reason being do you want to test that you get a value returned from all methods OR do you want to test that under different assumptions EACH method will return a login ?
For me its more important knowing that each method will return a login based on different use cases than a generic test that will return me pass / fail.
I hope that makes sense.
I would write one test for GetLoginsThatCanCallAction mocking the external objects. From your example, that would possibly mean mocking the Union calls. The reason being, when I am writing this code, I am not concerned with the logic being used in Union. (I have had cases where I haven't even written them yet).
If the union calls behavior can change, (IE it throws an exception), I would have a test for each of those. However, I would have my test-suite generating those test cases for me rather than trying to write them all by hand.
You are concerned that the GetLoginsThatCanCallAction behaves correctly. You also want to have control over what the Union calls return as well.
That being said, you would also want to have an automated test that executes the entire process that GetLoginsThatCanCallAction gets used in so that you are verifying the connections between the classes that you are mocking in the unit test. Barring that not being possible actually executing the process yourself manually.
One other note, if the class is hard to test. That is a code smell that your design is not as modular as it could be.
I would also avoid mocking internal methods of a class, if you need to do that to test the function. It is a sign that your class has another class hiding inside. Your class is doing more than one thing the S in SOLID
You should exercise only public API of unit under test. Your unit has single public method GetLoginsThatCanCallAction. It does not matter whether this method call other methods, or implemented as one large method. That's an implementation details. What really matters is whether this method correctly communicates with dependency and returns expected result:
// Arrange
Mock<IProcessData> processData = new Mock<IProcessData>();
processData.Setup(d => d.ProcessOwner).Returns(new[] { "Bob" });
var expected = new []{ "Bob", "Joe" };
// Act
var actual = roles.GetLoginsThatCanCallAction("Drink");
// Assert
processData.VerifyGet(d => d.ProcessOwner); // verify communication
CollectionAssert.AreEquivalent(expected, actual); // verify result

Unit testing code using IQueryable

I'm asked to write some unit tests for some functionality, but quite frankly I'm not so sure about the need or usefulness of doing so for this particular piece of code. I'm in no way trying to question the need or usefulness of unit testing in general.
The code in question is very trivial and gets used alot. Basically it's a wrapper around the .Skip() and .Take() extension methods. In my opinion the legitimacy of the methods as a whole is questionable.
The code is basically this:
public IQueryable<T> Page(IQueryable<T> query, int page, int size)
{
if(query == null) throw new ArgumentNullException("query");
if(page < 0) throw new ArgumentOutOfRangeException("page");
if(page < 0) throw new ArgumentOutOfRangeException("size");
return query.Skip(page * size).Take(size);
}
Of course I can unit test for the expected exceptions, but what else? Could very well be that I'm missing the point, so what's up with this?
You can just hand in a static collection by calling AsQueryable
List<T> dummyData = new List<T>();
//Add data
var result = Page(dummyData.AsQueryable(), 0, 10);
//Perform assertions on result.
If you are in-fact just trying to test that your pagination works correctly.
You can test quite a few things here:
Check for proper guards (the exceptions that are thrown when invalid parameters are passed).
Check that Skip was called with the correct parameter.
Check that Take was called with the correct parameter.
Check that Skip was called before Take.
Points 2 - 4 are best tested with a mock. A mocking framework comes in handy here.
This kind of testing is called "interaction-based testing".
You could also use "state-based testing" by calling the method under test with a list with data and check that the returned data is the correct subset.
A test for point 2 could look like this:
public void PageSkipsThePagesBeforeTheRequestedPage()
{
var sut = new YourClass();
var queryable = Substitute.For<IQueryable<int>>();
sut.Page(queryable, 10, 50);
queryable.Received().Skip(500);
}
This test uses NSubstitute as mocking framework.
I'm sure, there is a strong need to test this method.
First of all, because of the bug:
if(page < 0) throw new ArgumentOutOfRangeException("page");
if(page < 0) throw new ArgumentOutOfRangeException("size");
You're not checking the size variable in fact.
Anyway, there is no need to perform the "integrated" testing - you can simply mock your IQueryable object and perform the unit testing. (see this answer: How do I mock IQueryable<T>)
In my opinion, it is an absolutely right thing to do to test this method.
In fact, since IQueryable<T> may encapsulate an underlying data storage - which is the case of Entity Framework's queryables -, we're talking about integration tests.
In my case, if I'd need to test something like your piece of code, I'd store some test data in the database for later query for it.
Since I can expect the results, I can perform an assertion in order to check if the tested method returned the expected result.
UPDATE
Since I see some confusion with the downvote and some comments, I'd like to point out that I've answered this taking in account the fact that the answer is tagged as for Entity Framework and I guess that the queryable was obtained from the DbSet.

Reusing a verified Mock

I am doing ordered expectations in rhino mocks as described by ayende in this post. My code looks something like this:
using (_mocks.Ordered())
{
Expect.Call(() => _myMock.CallA());
Expect.Call(() => _myMock.CallB(40));
Expect.Call(() => _myMock.CallA());
}
_mocks.ReplayAll();
_myObjectUnderTest.DoStuff();
_mocks.VerifyAll();
After this I would like to add more expectations and test more of my object's methods. I want to do this because I have some basic test methods that do some setup on my test object, and I do not want to have to retest that functionality, so I just call the earlier test method. If I try and add more expectations after VerifyAll() I get an exception: "This action is invalid when the mock object is in verified state."
Part of my problem is that I don't really understand what all of the replay/verify stuff is doing, I just copied code. I am using strict mocks, so any setup code must have matching expectations or it fails. I do not want to duplicate the expectations for my setup code.
Is there a way to reset the mock to be ready to start over in some way?
Short answer: no. Now on to the long answer.
What the replay and verify stuff does is this. Before you call ReplayAll, you are telling Rhino what you expect the methods are going to do. You in a sense are recording calls to the mock objects you've created.
After you've recorded the method calls, you call ReplayAll telling Rhino you're now going to do 'something' that should execute the methods as recorded.
Last, you call VerifyAll asking Rhino to verify whether the methods were actually called as you've recorded them.
Now on to why you really should not want to re-use the mocks. With unit testing/TDD, your unit test should test as little as possible. This is to keep your unit tests simple and transparent. The whole idea of unit testing is that many many many small tests as a whole test the entire system.
For a very good presentation on TDD explaining this and other subjects, see http://www.infoq.com/presentations/integration-tests-scam.
P.S.: One small detail: As long as the methods don't return a result, you can write:
using (_mocks.Ordered())
{
Expect.Call(() => _myMock.CallA());
Expect.Call(() => _myMock.CallB(40));
Expect.Call(() => _myMock.CallA());
}
as:
using (_mocks.Ordered())
{
_myMock.CallA();
_myMock.CallB(40);
_myMock.CallA());
}
(at least with the latest version of Rhino)
Short answer: yes
Longer answer: Try the following
[Test]
public void RhinoMock_PerformMultipleChecks()
{
var myMock = MockRepository.GenerateDynamicMockWithRemoting<IComparable>();
// first round of checks
myMock.Expect(x => x.CompareTo("123")).Return(1);
myMock.Expect(x => x.CompareTo("-12")).Return(-1);
Assert.AreEqual(1, myMock.CompareTo("123"));
Assert.AreEqual(-1, myMock.CompareTo("-12"));
myMock.VerifyAllExpectations();
// reset
myMock.BackToRecord();
myMock.Replay();
// next round of checks
myMock.Expect(x => x.CompareTo(1.23)).Return(1);
myMock.Expect(x => x.CompareTo(-12)).Return(-1);
Assert.AreEqual(1, myMock.CompareTo(1.23));
Assert.AreEqual(-1, myMock.CompareTo(-12));
myMock.VerifyAllExpectations();
// reset
myMock.BackToRecord();
myMock.Replay();
// final round of checks
myMock.Expect(x => x.CompareTo(1.23m)).Return(1);
myMock.Expect(x => x.CompareTo(-12m)).Return(-111);
Assert.AreEqual(1, myMock.CompareTo(1.23m));
Assert.AreEqual(-111, myMock.CompareTo(-12m));
myMock.VerifyAllExpectations();
}

Categories

Resources