Playing around with Rhino Mocks, i just stumbled upon a strange behaviour, which I cannot understand.
Setting up my Stub the following way works as expected - 42 is returned
var generator = MockRepository.GenerateStub<INumberGenerator>();
generator.Stub(x => x.GetNumber()).Return(42);
Then I tried using the WhenCalled(Action<MethodInvocation> action) extension, which I used so far only for void functions:
generator.Stub(x => x.GetNumber()).WhenCalled(mi => mi.ReturnValue = 42);
This code throws me an exception Method 'INumberGenerator.GetNumber();' requires a return value or an exception to throw.. Ok, I've added .Return(55) - and now things start to get weird:
generator.Stub(x => x.GetNumber()).WhenCalled(mi => mi.ReturnValue = 42).Return(55);
Which now returns 42, instead of 55. Note that the MethodInvocation.ReturnValue only works when adding the .Return(..) statement which then has absolutely no effect on the returnvalue - which confuses me a lot. Can anybody explain this behaviour?
Rhino Mocks requires you to specify a Return() call at the end of an Expect() chain (in your case, when you're setting expectation for your stub), so that it can determine the type of the return result.
So, in effect, the return value in WhenCalled() is only used. Any value in Returns() would do (and not be used) as long as it is of the same type.
Not explicitly mentioned in the documentation I think.
Related
I think the code will explain this issue better than my poor title.
_httpContextBase is a HttpContextBase but I don't imagine that matters. _httpCookiecollection is just a HttpCookieCollection
//Works fine
_httpContextBase.Stub(c => c.Response.Cookies).Return(_httpCookieCollection);
//Fails after attempting to stub the second line. "Object reference not set to an instance of an object". First line passes fine.
_httpContextBase.Stub(c => c.Response.Cookies).Return(_httpCookieCollection);
_httpContextBase.Stub(c => c.Request.Cookies).Return(_httpCookieCollection);
//Work around
var responseBaseMock = MockRepository.GenerateMock<HttpResponseBase>();
responseBaseMock.Stub(r => r.Cookies).Return(_httpCookieCollection);
_httpContextBase.Stub(c => c.Response).Return(responseBaseMock);
var requestBaseMock = MockRepository.GenerateMock<HttpRequestBase>();
requestBaseMock.Stub(r => r.Cookies).Return(_httpCookieCollection);
_httpContextBase.Stub(c => c.Request).Return(requestBaseMock);
Imagine the above tests are each their own method. Each comment explains what happens when the code below it is run.
The first item works, the second item fails and the third item is my work around. What I want to know is why does the second item fail as I can't seem to figure it out.
Stack trace for item 2 (the same stack trace even if lines 1 and 2 are inverted)
System.NullReferenceException : Object reference not set to an instance of an object.
at Api.Tests.Client.CookieTests.<>c.<Test>b__12_1(HttpContextBase c) in Api.Tests\Client\CookieTests.cs:line 113
at Rhino.Mocks.RhinoMocksExtensions.Expect[T,R](T mock, Function`2 action)
at Rhino.Mocks.RhinoMocksExtensions.Stub[T,R](T mock, Function`2 action)
at .Api.Tests.Client.CookieTests.Test() in .Api.Tests\Client\CookieTests.cs:line 113
I know I am a bit late to the party and this might not be important to the asker anymore but I will still answer for anyone new to Rhino Mocks.
When mocking with Rhino Mocks, if you call the method multiple times, you need to append .Repeat.Once() to each different stub. (.Once()) can be replaced with the appropriate number of times that you need to use that response before getting a new response using .Twice() or .Times(x) where x is replaced with a numeric value for the number of times that you need the call made.
I haven't tried your code, so I may not be right. But it could be that _httpContextBase.Request is null. If that is the case, and the reason for the NullReferenceException, then it would appear that _httpContextBase.Response is not null, as that doesn't have the same problem.
I don't know that object is set up in your test, but that might be something to look at. Also, have you tried them the other way around? I would guess that it's something to do with .Request, and not that it's the second stub.
I know you haven't asked for it, but I'll also suggest a different approach that I've found useful for mocking complex things like HttpContext. Write an abstraction interface that exposes the parts that you want to use (such as ResponseCookies and RequestCookies). Your implementation of that interface can diretly use the HttpContext members, but your other classes no longer depend on, and you have a very simple interface to mock or stub.
I have come across a very strange behavior in moq and I cannot understand whether it's a bug or I am doing something wrong. Here is the example:
List<CustomerDataTransaction> transactions0 = GetTransactionsSomehow();
List<CustomerDataTransaction> transactions1 = GetTransactionsSomehow();
var portfolioTransactions0 = new List<IPortfolioTransaction>();
var portfolioTransactions1 = new List<IPortfolioTransaction>();
m_TransactionMapperMock
.Setup(m => m.CreatePortfolioTransactions(transactions0))
.Returns(portfolioTransactions0);
m_TransactionMapperMock
.Setup(m => m.CreatePortfolioTransactions(transactions1))
.Returns(portfolioTransactions1);
I have checked that transaction0 is not equal to transactions1, so it's for sure different lists. But the mock returns portfolioTransactions1 twice when called with different parameters (transactions0 and transactions1). I tried to figure out what was wrong, but I did not find any reasons. Then I have added dummy elements to each of the lists and that has fixed it, mock started to return different values as planned. Is this a bug of Mock or I don't get something? As far as I understand the values inside the list should not affect it at all.
P.S. I don't know if it's important or not but the method accepts IEnumerable<CustomerDataTransaction>
Consider trying:
It.Is<IEnumerable<CustomerDataTransaction>>(t => t == transactions1))
From memory I thought Moq used reference equality
Expanding on NinjaNye's answer, using It.Is satisfies the test is because it ensures that you are looking at the exact instance of the object, not the equality operator.
With your testing framework, if you say Assert.NotEqual and give it two objects, it uses the equality operator and says one empty list equal to the other. Think about being able to compare objectA.Property1 to objectA.Property2. It makes sense that Assert.Equal would look at the values, not the instance of the value.
Xunit provides a method Assert.Same, which will provide the same functionality as Moq's It.Is<>, verifying it is the same instance of the object. I believe that most of the popular testing frameworks today provide similar behavior.
I spent a few days writing a test, then had to add a property at the last minute to fix one of the issues I found in writing my test. Since adding that property I have been stuck just trying to get the mocking framework to function.
Here is my code.
using (_mockRepository.Record())
{
_mockBattleDao.Expect(b => b.GetUnprocessedActions(gameId, round)).Return(roundResolvingItems);
_mockDao.Expect(b => b.GetMidGameCharacterStats(gameId, round)).Return(midGameCharacterStats);
_mockBattleDao.Expect(b => b.GetAmbientCharacterBuffs(_mockTiersHelper, gameId, round)).Return(new List<Buff>());
_mockBattleDao.Expect(b => b.GetActiveTriggerBuffs(_mockTiersHelper, gameId, round)).Return(triggerBuffs);
_mockBattleDao.Expect(b => b.GetActiveAmbientBuffs(_mockTiersHelper, gameId, round)).Return(new List<Buff>());
_mockDao.Expect(b => b.GetGame(gameId)).Return(new Common.Entities.Game { CompletionType = "single party down" });
_mockDao.Expect(b => b.GetAbilityById(1337)).Return(ability).Repeat.Times(3);
_mockDao.Expect(b => b.GetAbilityById(1727)).Return(attackAbility).Repeat.Times(4);
_mockTiersHelper.Expect(b => b.AddStatistic(Arg<StatAndCount>.Is.Anything)).Repeat.Times(3);
SetupResult.For(_mockTiersHelper.Round).Return(round);
}
TiersCalculationContainer container;
using (_mockRepository.Playback())
{
container = engine.ProcessTiers();
}
I Know the AAA syntax is the new hotness but I have a large test that is complete but for this and I don't want to go back and rewrite.
When code execution reaches the closing "}" of the "Playback" using I get this exception:
ExpectationViolationException
TiersCalculationContainer.get_Round(); Expected #1, Actual #0.
When debugging the test the property "Round" is read correctly and retursn the value I mocked for it so I know it was called.
I can't find any information online about this. There seems to be about 100 ways to mock a property in Rhino mocks. None of them are working and this is getting really frustrating.
I have also tried mocking all of these ways as well (and more)
_mockTiersHelper.Expect(b => b.Round).Return(round);
Expect.Call(_mockTiersHelper.Round).PropertyBehavior();
_mockTiersHelper.Round = round;
That is a lot of expectations for one test, I would recommend testing the behavior of each of these objects separately and then testing only that they are called properly at the integration point.
Aside from that I think your problem is a logic issue not a syntax issue, if you are setting up the mock according to the documentation and getting an unexpected behavior its a bug in your code or your test.
I think the answer to this may be that this is a bug. I dumped Rhino and went back to Moq. 10 minutes and I was up and running. Now my tests pass. Thank you Moq!
I'm working on understanding a bit more about Setup and unit testing with Moq. I've run into a slight problem though.
What I want to do is something like this:
view.Setup(x => x.GetReference("object1")).Returns(object1);
view.Setup(x => x.GetReference("object2")).Returns(null);
However, when I make my call this way, I never hit the block of code that would react to the Null statement. How am I supposed to set up my Setups so that they will behave in a specific way when they are called by a specific argument?
The moq overloads two ways to return a value:
instance: Returns(instance);
delegate(Func<T>): Returns(()=>new Foo());
I think that the problem is caused from the ambiguousness for which Returns method is to be used.
So, you need to pass in the explicit type of NULL for the second setup of your code as the following ways:
view.Setup(x => x.GetReference("object2")).Returns((ExplicitType)null);
view.Setup(x => x.GetReference("object2")).Returns(() => null);
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.