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.
Related
While refactoring unit tests in a project, I found some tests that should have been failing but were succeeding for some mysterious reason. After removing irrelevant code and moving everything into one method, the following minimal example still has the original behavior:
[Test]
public void TestThatShouldFail()
{
// Arrange
var mock = MockRepository.GenerateStub<ISomething>();
mock.Stub(wi => wi.SomeProperty).Return(MockRepository.GenerateStub<ISomeProperty>());
mock.SomeProperty.Stub(t => t.SomethingElse).Return(new SomethingElse());
...
// Act
_foo.Foo();
// Assert
mock.AssertWasCalled(wi => wi.SomeProperty.DoSomething());
}
The variable mock is never passed, exposed or exported in any way which is available to the code running in the Act part. Still, the test passes, which should mean that the DoSomething method was called on the SomeProperty of the mock variable, which is obviously wrong.
How can this happen?
The code above is already a result of some investigation, so it only contains the lines relevant to the problem and its solution.
The culprit is the last line of the Arrange part.
As it turns out, the Assert line doesn't really check whether the DoSomething method was called on SomeProperty, but whether SomeProperty was accessed on mock! And we actually did that in the last Arrange line, when stubbing a method on it.
I couldn't find any official documentation for it, so I can only assume that it considers only the first level of the expression in its argument, so one shouldn't pass expressions with multiple levels of member access (dots) to AssertWasCalled (or AssertWasNotCalled).
(The proper way to check it would be mock.SomeProperty.AssertWasCalled(wi => wi.DoSomething()), but it wasn't needed here.)
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.
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!
We have just released a re-written(for the 3rd time) module for our proprietary system. This module, which we call the Load Manager, is by far the most complicated of all the modules in our system to date. We are trying to get a comprehensive test suite because every time we make any kind of significant change to this module there is hell to pay for weeks in sorting out bugs and quirks. However, developing a test suite has proven to be quite difficult so we are looking for ideas.
The Load Manager's guts reside in a class called LoadManagerHandler, this is essentially all of the logic behind the module. This handler calls upon multiple controllers to do the CRUD methods in the database. These controllers are essentially the top layer of the DAL that sits on top and abstracts away our LLBLGen generated code.
So it is easy enough to mock these controllers, which we are doing using the Moq framework. However the problem comes in the complexity of the Load Manager and the issues that we receive aren't in dealing with the simple cases but the cases where there is a substantial amount of data contained within the handler.
To briefly explain the load manager contains a number of "unloaded" details, sometimes in the hundreds, that are then dropped into user created loads and reship pools. During the process of creating and populating these loads there is a multitude of deletes, changes, and additions that eventually cause issues to appear. However, because when you mock a method of an object the last mock wins, ie:
jobDetailControllerMock.Setup(mock => mock.GetById(1)).Returns(jobDetail1);
jobDetailControllerMock.Setup(mock => mock.GetById(2)).Returns(jobDetail2);
jobDetailControllerMock.Setup(mock => mock.GetById(3)).Returns(jobDetail3);
No matter what I send to jobDetailController.GetById(x) I will always get back jobDetail3. This makes testing almost impossible because we have to make sure that when changes are made all points are affected that should be affected.
So, I resolved to using the test database and just allowing the reads and writes to occur as normal. However, because you can't(read: should not) dictate the order of your tests, tests that are run earlier could cause tests that run later to fail.
TL/DR: I am essentially looking for testing strategies for data oriented code that is quite complex in nature.
As noted by Seb, you can indeed use a range matching:
controller.Setup(x => x.GetById(It.IsInRange<int>(1, 3, Range.Inclusive))))).Returns<int>(i => jobs[i]);
This code uses the argument passed to the method to calculate which value to return.
To get around the "last mock wins" with Moq, you could use the technique from this blog:
Moq Triqs - Successive Expectations
EDIT:
Actually you don't even need that. Based on your example, Moq will return different values based on the method argument.
public interface IController
{
string GetById(int id);
}
class Program
{
static void Main(string[] args)
{
var mockController = new Mock<IController>();
mockController.Setup(x => x.GetById(1)).Returns("one");
mockController.Setup(x => x.GetById(2)).Returns("two");
mockController.Setup(x => x.GetById(3)).Returns("three");
IController controller = mockController.Object;
Console.WriteLine(controller.GetById(1));
Console.WriteLine(controller.GetById(3));
Console.WriteLine(controller.GetById(2));
Console.WriteLine(controller.GetById(3));
Console.WriteLine(controller.GetById(99) == null);
}
}
Output is:
one
three
two
three
True
It sounds like LoaderManagerHandler does... quite a bit of work. "Manager" in a class name always somewhat worries me... from a TDD standpoint, it might be worth thinking about breaking the class up appropriately if possible.
How long is this class?
I've never used Moq, but it seems that it should be able to match a mock invocation by argument(s) supplied.
A quick look at the Quick Start documentation has the following excerpt:
//Matching Arguments
// any value
mock.Setup(foo => foo.Execute(It.IsAny<string>())).Returns(true);
// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true);
// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true);
I think you should be able to use the second example above.
A simple testing technique is to make sure everytime a bug is logged against a system, make sure a unit test is written covering that case. You can build up a pretty solid set of tests just from that technique. And even better you won't run into the same thing twice.
No matter what I send to jobDetailController.GetById(x) I will always get back jobDetail3
You should spend more time debugging your tests because what is happening is not how Moq behaves. There is a bug in your code or tests causing something to misbehave.
If you want to make repeated calls with the same inputs but different outputs you could also use a different mocking framework. RhinoMocks supports the record/playback idiom. You're right this is not always what you want with regards to enforcing call order. I do prefer Moq myself for its simplicity.