繁体   English   中英

如何使用Rhino Mocks将IQueryable <T> .Where(Func <T,bool>)存根?

[英]How do you stub IQueryable<T>.Where(Func<T, bool>) with Rhino Mocks?

在我正在进行的.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);

所以我的问题是:

如何使用RhinoMocks模拟或存根IQueryable.Where函数并通过此测试?

如果我当前的设置不允许我模拟或存根IQueryable,那么给出一个合理的解释原因。

感谢您阅读这个长篇大论的问题。

不使用Rhino模拟,您可以创建一个List,然后在其上调用.AsQueryable()。 例如

var actionTypeList = new List<ActionType>() {
    new ActionType {},  //put your fake data here
    new ActionType {}
};

var actionTypeRepo = actionTypeList.AsQueryable();

这至少会让你成为一个虚假的存储库,但它不会让你验证方法被调用。

扩展方法Where ,这不是由IQueriable接口实现的方法。 看看IQueriable的成员: http//msdn.microsoft.com/en-us/library/system.linq.iqueryable_members.aspx

扩展方法是静态的,不能被模拟。 IMO,没有必要模仿Where ,因为它是语言的一部分。 您应该只模拟存储库。

编辑,示例:

[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
    }

}

注意:您不需要期望调用,因为您的方法取决于模拟的返回值。 如果它不会调用它,它将在断言上失败。 这使您的测试更容易维护。

我最初想模拟像'IQueryable.Where(Func)'这样的调用,但我认为它是在错误的级别进行测试。 相反,在我的测试中,我只是模拟了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();

我有类似的问题,我试图将谓词表达式存根到包含字符串的Find-method,但String当然是引用类型和不可变的。 没有成功,直到我创建testPredicate,我传递给存根,实际SUT,最后断言。 下面的代码工作。

    [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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM