如何使用 Rhino Mocks 存根 IQueryable.Where(Func) ?
在我现在正在处理的 .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
}
我很难弄清楚如何存根或模拟该
actionTypeQuery.Where(x => x.Name == "debug")
部分。
这是我到目前为止得到的:
[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();
}
}
[注意:类名已更改以保护无辜者]
但这会失败,并出现 System.NullReferenceException
所以
_actionQuery.Expect(x => x.Where(y => y.Name == "debug")).Return(_actionQuery);
我的问题是:
如何模拟或存根 IQueryable。在哪里使用 RhinoMocks 并让这个测试通过?
如果我当前的设置不允许我模拟或存根 IQueryable,请给出合理的解释。
感谢您阅读这个非常长的问题。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不使用Rhino模拟,您可以创建一个列表,然后对其调用.AsQueryable()。 例如,
这至少会给你一个假存储库,但它不会让你验证方法是否被调用。
Without using Rhino mocks, you can create a List and then call .AsQueryable() on it. e.g.
That will at least get you a fake repository, but it won't let you verify that methods were called.
其中
是一个扩展方法,这不是接口IQueriable实现的方法。 查看 IQueriable 的成员: http://msdn.microsoft .com/en-us/library/system.linq.iqueryable_members.aspx扩展方法是静态的,无法模拟。 IMO,没有必要模拟
Where
,因为它是语言的一部分。 您应该只模拟存储库。编辑,示例:
注意:您不需要期待调用,因为您的方法取决于模拟的返回值。 如果它不调用它,它的断言就会失败。 这使您的测试更易于维护。
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.aspxAn 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:
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.
我最初也想模拟像“IQueryable.Where(Func)”这样的调用,但我认为它在错误的级别进行测试。 相反,在我的测试中,我只是模拟了 IQueryable,然后检查结果:
I initially wanted to mock out calls like 'IQueryable.Where(Func)' too but I think it is testing at the wrong level. Instead in my tests I just mocked out IQueryable and then check the result:
我也遇到过类似的问题,我尝试将谓词表达式存根到包含字符串的 Find-method,但 String 是引用类型,当然是不可变的。 在我创建 testPredicate 并将其传递给存根、实际 SUT 并最终进行断言之前,没有成功。 下面的代码有效。
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. No success until I've create testPredicate which I pass to stub, actual SUT and finally to assert. Below code works.