In the .net 3.5 project that I am working on right now, I was writing some tests for a service class.
public class ServiceClass : IServiceClass
{
private readonly IRepository _repository;
public ServiceClass(IRepository repository)
{
_repository = repository;
}
#region IServiceClass Members
public IEnumerable<ActionType> GetAvailableActions()
{
IQueryable<ActionType> actionTypeQuery = _repository.Query<ActionType>();
return actionTypeQuery.Where(x => x.Name == "debug").AsEnumerable();
}
#endregion
}
and I was having a hard time figuring out how to stub or mock the
actionTypeQuery.Where(x => x.Name == "debug")
part.
Here's what I got so far:
[TestFixture]
public class ServiceClassTester
{
private ServiceClass _service;
private IRepository _repository;
private IQueryable<ActionType> _actionQuery;
[SetUp]
public void SetUp()
{
_repository = MockRepository.GenerateMock<IRepository>();
_service = new ServiceClass(_repository);
}
[Test]
public void heres_a_test()
{
_actionQuery = MockRepository.GenerateStub<IQueryable<ActionType>>();
_repository.Expect(x => x.Query<ActionType>()).Return(_actionQuery);
_actionQuery.Expect(x => x.Where(y => y.Name == "debug")).Return(_actionQuery);
_service.GetAvailableActions();
_repository.VerifyAllExpectations();
_actionQuery.VerifyAllExpectations();
}
}
[Note: class names have been changed to protect the innocent]
But this fails with a System.NullReferenceException
at
_actionQuery.Expect(x => x.Where(y => y.Name == "debug")).Return(_actionQuery);
So my question is:
How do I mock or stub the IQueryable.Where function with RhinoMocks and get this test to pass?
If my current setup won't allow me to mock or stub IQueryable, then give a reasoned explanation why.
Thanks for reading this epically long question.
Without using Rhino mocks, you can create a List and then call .AsQueryable() on it. e.g.
var actionTypeList = new List<ActionType>() {
new ActionType {}, //put your fake data here
new ActionType {}
};
var actionTypeRepo = actionTypeList.AsQueryable();
That will at least get you a fake repository, but it won't let you verify that methods were called.
Where
is an extension method, this is not a method implemented by the interface IQueriable. Look at the members of IQueriable: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable_members.aspx
An extension method is static and can't be mocked. IMO, there is no need to mock Where
, because it's part of the language. You should only mock the repository.
Edit, Example:
[TestFixture]
public class ServiceClassTester
{
private ServiceClass _service;
private IRepository _repository;
private IQueryable<ActionType> _actionQuery;
[SetUp]
public void SetUp()
{
_service = new ServiceClass(_repository);
// set up the actions. There is probably a more elegant way than this.
_actionQuery = (new List<ActionType>() { ActionA, ActionB }).AsQueryable();
// setup the repository
_repository = MockRepository.GenerateMock<IRepository>();
_repository.Stub(x => x.Query<ActionType>()).Return(_actionQuery);
}
[Test]
public void heres_a_test()
{
// act
var actions = _service.GetAvailableActions();
// assert
Assert.AreEqual(1, actions.Count());
// more asserts on he result of the tested method
}
}
Note: you don't need to expect the call, because your method depends on the return value of the mock. If it wouldn't call it, it would fail on the asserts. This makes your test easier to maintain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With