[英]How do you stub IQueryable<T>.Where(Func<T, bool>) with Rhino Mocks?
In the .net 3.5 project that I am working on right now, I was writing some tests for a service class. 在我正在进行的.net 3.5项目中,我正在为服务类编写一些测试。
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 但是,这会因
System.NullReferenceException
而失败
_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? 如何使用RhinoMocks模拟或存根IQueryable.Where函数并通过此测试?
If my current setup won't allow me to mock or stub IQueryable, then give a reasoned explanation why. 如果我当前的设置不允许我模拟或存根IQueryable,那么给出一个合理的解释原因。
Thanks for reading this epically long question. 感谢您阅读这个长篇大论的问题。
Without using Rhino mocks, you can create a List and then call .AsQueryable() on it. 不使用Rhino模拟,您可以创建一个List,然后在其上调用.AsQueryable()。 eg
例如
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. 扩展方法
Where
,这不是由IQueriable接口实现的方法。 Look at the members of IQueriable: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable_members.aspx 看看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. IMO,没有必要模仿
Where
,因为它是语言的一部分。 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.
这使您的测试更容易维护。
I initially wanted to mock out calls like 'IQueryable.Where(Func)' too but I think it is testing at the wrong level. 我最初想模拟像'IQueryable.Where(Func)'这样的调用,但我认为它是在错误的级别进行测试。 Instead in my tests I just mocked out IQueryable and then check the result:
相反,在我的测试中,我只是模拟了IQueryable,然后检查结果:
// Setup a dummy list that will be filtered, queried, etc
var actionList = new List<ActionType>()
{
new ActionType() { Name = "debug" },
new ActionType() { Name = "other" }
};
_repository.Expect(x => x.Query<ActionType>()).Return(actionList);
var result = _service.GetAvailableActions().ToList();
// Check the logic of GetAvailableActions returns the correct subset
// of actionList, etc:
Assert.That(result.Length, Is.EqualTo(1));
Assert.That(result[0], Is.EqualTo(actionList[0]);
_repository.VerifyAllExpectations();
I've had similar problem where I tried to stub predicate expression to Find-method which contains string, but String is reference type and immutable of course. 我有类似的问题,我试图将谓词表达式存根到包含字符串的Find-method,但String当然是引用类型和不可变的。 No success until I've create testPredicate which I pass to stub, actual SUT and finally to assert.
没有成功,直到我创建testPredicate,我传递给存根,实际SUT,最后断言。 Below code works.
下面的代码工作。
[Test()]
public void Search_Apartment_With_Spesific_Address()
{
//ARRANGE
var repositoryMock = MockRepository.GenerateMock<IApartmentRepository>();
var notificationMock = MockRepository.GenerateMock<INotificationService>();
var service = new ApartmentService(repositoryMock, notificationMock);
var apartment = new List<Apartment> {new Apartment {Address = "Elm Street 2"}}.AsQueryable();
Expression<Func<Apartment, bool>> testPredicate = a => a.Address == "Elm Street 2";
repositoryMock.Stub(x => x.Find(testPredicate)).Return(apartment);
//ACT
service.Find(testPredicate);
//ASSERT
repositoryMock.AssertWasCalled(x => x.Find(testPredicate));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.